void ValueToString(unsigned char *str, unsigned char val)
{
//電壓值=轉換結果*2.5V/255,式中的25隱含了一位十進制小數
val = (val*25) / 255;
str[0] = (val/10) + '0'; //整數位字符
str[1] = '.'; //小數點
str[2] = (val%10) + '0'; //小數位字符
str[3] = 'V'; //電壓單位
str[4] = '\0'; //結束符
}
就val = (val*25) / 255;這句看不懂,255我理解是PCF89C51模數轉換器的量程,但是乘以25是什么意思了,為何又要除以255?這里的val是從I2C讀取到的電壓值。
我覺得是對A/D和D/A理解太模糊導致的。
整體代碼如下:
- #include <reg52.h>
- bit flag300ms = 1; //300ms定時標志
- unsigned char T0RH = 0; //T0重載值的高字節
- unsigned char T0RL = 0; //T0重載值的低字節
- void ConfigTimer0(unsigned int ms);
- unsigned char GetADCValue(unsigned char chn);
- void ValueToString(unsigned char *str, unsigned char val);
- extern void I2CStart();
- extern void I2CStop();
- extern unsigned char I2CReadACK();
- extern unsigned char I2CReadNAK();
- 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; //開總中斷
- ConfigTimer0(10); //配置T0定時10ms
- InitLcd1602(); //初始化液晶
- LcdShowStr(0, 0, "AIN0 AIN1 AIN3"); //顯示通道指示
-
- while (1)
- {
- if (flag300ms)
- {
- flag300ms = 0;
- //顯示通道0的電壓
- val = GetADCValue(0); //獲取ADC通道0的轉換值
- ValueToString(str, val); //轉為字符串格式的電壓值
- LcdShowStr(0, 1, str); //顯示到液晶上
- //顯示通道1的電壓
- val = GetADCValue(1);
- ValueToString(str, val);
- LcdShowStr(6, 1, str);
- //顯示通道3的電壓
- val = GetADCValue(3);
- ValueToString(str, val);
- LcdShowStr(12, 1, str);
- }
- }
- }
- /* 讀取當前的ADC轉換值,chn-ADC通道號0~3 */
- unsigned char GetADCValue(unsigned char chn)
- {
- unsigned char val;
-
- I2CStart();
- if (!I2CWrite(0x48<<1)) //尋址PCF8591,如未應答,則停止操作并返回0
- {
- I2CStop();
- return 0;
- }
- I2CWrite(0x40|chn); //寫入控制字節,選擇轉換通道
- I2CStart();
- I2CWrite((0x48<<1)|0x01); //尋址PCF8591,指定后續為讀操作
- I2CReadACK(); //先空讀一個字節,提供采樣轉換時間
- val = I2CReadNAK(); //讀取剛剛轉換完的值
- I2CStop();
-
- return val;
- }
- /* ADC轉換值轉為實際電壓值的字符串形式,str-字符串指針,val-AD轉換值 */
- void ValueToString(unsigned char *str, unsigned char val)
- {
- //電壓值=轉換結果*2.5V/255,式中的25隱含了一位十進制小數
- val = (val*25) / 255;
- str[0] = (val/10) + '0'; //整數位字符
- str[1] = '.'; //小數點
- str[2] = (val%10) + '0'; //小數位字符
- str[3] = 'V'; //電壓單位
- str[4] = '\0'; //結束符
- }
-
- void ConfigTimer0(unsigned int ms)
- {
- unsigned long tmp; //臨時變量
-
- tmp = 11059200 / 12; //定時器計數頻率
- tmp = (tmp * ms) / 1000; //計算所需的計數值
- tmp = 65536 - tmp; //計算定時器重載值
- tmp = tmp + 12; //補償中斷響應延時造成的誤差
- T0RH = (unsigned char)(tmp>>8); //定時器重載值拆分為高低字節
- T0RL = (unsigned char)tmp;
- TMOD &= 0xF0; //清零T0的控制位
- TMOD |= 0x01; //配置T0為模式1
- TH0 = T0RH; //加載T0重載值
- TL0 = T0RL;
- ET0 = 1; //使能T0中斷
- TR0 = 1; //啟動T0
- }
-
- void InterruptTimer0() interrupt 1
- {
- static unsigned char tmr300ms = 0;
-
- TH0 = T0RH; //重新加載重載值
- TL0 = T0RL;
- tmr300ms++;
- if (tmr300ms >= 30) //定時300ms
- {
- tmr300ms = 0;
- flag300ms = 1;
- }
- }
復制代碼
|