模拟技术
代码相关:
/**********Lcd1602.c**************/
#include < reg52.h >
#define LCD1602_DB P2
sbit LCD1602_RS = P0^3;
sbit LCD1602_RW = P0^2;
sbit LCD1602_E = P0^1;
void LcdWaitReady()
{
unsigned char sta;
LCD1602_DB = 0xFF;
LCD1602_RS = 0;
LCD1602_RW = 1;
do {
LCD1602_E = 1;
sta = LCD1602_DB; //读取状态字
LCD1602_E = 0;
} while (sta & 0x80); //bit7等于1表示液晶正忙,重复检测直到其等于0为止
}
/* 向LCD1602液晶写入一字节命令,cmd-待写入命令值 */
void LcdWriteCmd(unsigned char cmd)
{
LcdWaitReady();
LCD1602_RS = 0;
LCD1602_RW = 0;
LCD1602_DB = cmd;
LCD1602_E = 1;
LCD1602_E = 0;
}
/* 向LCD1602液晶写入一字节数据,dat-待写入数据值 */
void LcdWriteDat(unsigned char dat)
{
LcdWaitReady();
LCD1602_RS = 1;
LCD1602_RW = 0;
LCD1602_DB = dat;
LCD1602_E = 1;
LCD1602_E = 0;
}
void LcdSetCursor(unsigned char x, unsigned char y)
{
unsigned char addr;
if (y == 0) //由输入的屏幕坐标计算显示RAM的地址
addr = 0x00 + x; //第一行字符地址从0x00起始
else
addr = 0x40 + x; //第二行字符地址从0x40起始
LcdWriteCmd(addr | 0x80); //设置RAM地址
}
void LcdShowStr(unsigned char x, unsigned char y, unsigned char *str)
{
LcdSetCursor(x, y); //设置起始地址
while (*str != '�') //连续写入字符串数据,直到检测到结束符
{
LcdWriteDat(*str++);
}
}
/* 初始化1602液晶 */
void InitLcd1602()
{
LcdWriteCmd(0x38);
LcdWriteCmd(0x0C);
LcdWriteCmd(0x06);
LcdWriteCmd(0x01);
}
/*********************IIC*******************/
#include < reg52.h >
#include < intrins.h >
#define Delay() {_nop_();_nop_();_nop_();_nop_();_nop_();}
sbit I2C_SCL = P3^7;
sbit I2C_SDA = P3^6;
/* 起始信号 */
void I2CStart()
{
I2C_SDA = 1;
I2C_SCL = 1;
Delay();
I2C_SDA = 0;
Delay();
I2C_SCL = 0;
}
/* 停止信号 */
void I2CStop()
{
I2C_SCL = 0; //首先确保SDA、SCL都是低电平
I2C_SDA = 0;
Delay();
I2C_SCL = 1; //先拉高SCL
Delay();
I2C_SDA = 1; //再拉高SDA
Delay();
}
/* I2C总线写操作,dat-待写入字节,返回值-从机应答位的值 */
bit I2CWrite(unsigned char dat)
{
bit ack;
unsigned char BitCnt;
for (BitCnt=0x80; BitCnt!=0; BitCnt > >=1)
{
if ((BitCnt&dat) == 0)
I2C_SDA = 0;
else
I2C_SDA = 1;
Delay();
I2C_SCL = 1; //拉高SCL
Delay();
I2C_SCL = 0; //再拉低SCL,完成一个位周期
}
I2C_SDA = 1;
Delay();
I2C_SCL = 1;
ack = I2C_SDA;
Delay();
I2C_SCL = 0;
return (ack);
}
/* I2C总线读操作,并发送应答信号或者非应答信号,如果cnt为1则发送应答信号,
如果cnt为非1的值则发送非应答信号,返回值-读到的字节 */
unsigned char I2CReadACKORNOT(bit cnt)
{
unsigned char BitCnt;
unsigned char dat;
I2C_SDA = 1; //首先确保主机释放SDA
for (BitCnt=0x80; BitCnt!=0; BitCnt > >=1) //从高位到低位依次进行
{
Delay();
I2C_SCL = 1; //拉高SCL
if(I2C_SDA == 0) //读取SDA的值
dat &= ~BitCnt; //为0时,dat中对应位清零
else
dat |= BitCnt; //为1时,dat中对应位置1
Delay();
I2C_SCL = 0; //再拉低SCL,以使从机发送出下一位
}
if(cnt)
I2C_SDA = 0; //8位数据发送完后,拉低SDA,发送应答信号
else
I2C_SDA = 1;
Delay();
I2C_SCL = 1; //拉高SCL
Delay();
I2C_SCL = 0; //再拉低SCL完成应答位,并保持住总线
return dat;
}
/******************main.c*************************/
#include < reg52.h >
bit flags = 1;
unsigned char GetValue(unsigned char chn);
void NumToString(unsigned char *str, unsigned char val);
extern void I2CStart();
extern void I2CStop();
unsigned char I2CReadACKORNOT(bit cnt);
extern bit I2CWrite(unsigned char dat);
extern void InitLcd1602();
extern void LcdShowStr(unsigned char x, unsigned char y, unsigned char *str);
void main()
{
unsigned char val;
unsigned char str[10];
EA = 1; //开总中断
TMOD &= 0xF0; //清零T0的控制位
TMOD |= 0x01; //配置T0为模式1
TH0 = (65536-9216)/256; //加载T0重载值,定时10ms
TL0 = (65536-9216)%256;
ET0 = 1; //使能T0中断
TR0 = 1; //启动T0
InitLcd1602(); //初始化液晶
LcdShowStr(0, 0, "AN0: AN1: AN3:"); //显示通道指示
while (1)
{
if (flags)
{
flags = 0;
//显示通道0的电压
val = GetValue(0); //获取ADC通道0的转换值
NumToString(str, val); //转为字符串格式的电压值
LcdShowStr(0, 1, str); //显示到液晶上
//显示通道1的电压
val = GetValue(1);
NumToString(str, val);
LcdShowStr(6, 1, str);
//显示通道3的电压
val = GetValue(3);
NumToString(str, val);
LcdShowStr(12, 1, str);
}
}
}
unsigned char GetValue(unsigned char chn)
{
unsigned char val;
I2CStart();
if(I2CWrite(0x48< < 1))
{
I2CStop();
return 0;
}
I2CWrite(0x40 | chn);
I2CStart();
I2CWrite(0x48< < 1 | 0x01);
I2CReadACKORNOT(1);
val = I2CReadACKORNOT(0);
I2CStop();
return val;
}
void NumToString(unsigned char *str, unsigned char val)
{
val = (val*50)/255;
str[0] = (val/10) + '0';
str[1] = '.';
str[2] = (val%10) + '0';
str[3] = '�';
}
/* T0中断服务函数 */
void InterruptTimer0() interrupt 1
{
static unsigned char tm100ms = 0;
TH0 = (65536-9216)/256; //加载T0重载值
TL0 = (65536-9216)%256;
tm100ms++;
if (tm100ms >= 10) //定时100ms
{
tm100ms = 0;
flags = 1;
}
}
AN3通道测得实际电压变化,通过滑动变阻器可以改变相应的值;AN0通道测得光敏电阻的阻值;AN1测得热敏电阻的相应阻值,需要货源才会变化值。
全部0条评论
快来发表一下你的评论吧 !