代碼相關:
/**********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測得熱敏電阻的相應阻值,需要貨源才會變化值。
評論
查看更多