標(biāo)題:
看不懂單片機代碼DA/AD這里的轉(zhuǎn)化
[打印本頁]
作者:
哈蘭德
時間:
2023-6-16 22:05
標(biāo)題:
看不懂單片機代碼DA/AD這里的轉(zhuǎn)化
void ValueToString(unsigned char *str, unsigned char val)
{
//電壓值=轉(zhuǎn)換結(jié)果*2.5V/255,式中的25隱含了一位十進制小數(shù)
val = (val*25) / 255;
str[0] = (val/10) + '0'; //整數(shù)位字符
str[1] = '.'; //小數(shù)點
str[2] = (val%10) + '0'; //小數(shù)位字符
str[3] = 'V'; //電壓單位
str[4] = '\0'; //結(jié)束符
}
就val = (val*25) / 255;這句看不懂,255我理解是PCF89C51模數(shù)轉(zhuǎn)換器的量程,但是乘以25是什么意思了,為何又要除以255?這里的val是從I2C讀取到的電壓值。
我覺得是對A/D和D/A理解太模糊導(dǎo)致的。
整體代碼如下:
#include <reg52.h>
bit flag300ms = 1; //300ms定時標(biāo)志
unsigned char T0RH = 0; //T0重載值的高字節(jié)
unsigned char T0RL = 0; //T0重載值的低字節(jié)
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的轉(zhuǎn)換值
ValueToString(str, val); //轉(zhuǎn)為字符串格式的電壓值
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);
}
}
}
/* 讀取當(dāng)前的ADC轉(zhuǎn)換值,chn-ADC通道號0~3 */
unsigned char GetADCValue(unsigned char chn)
{
unsigned char val;
I2CStart();
if (!I2CWrite(0x48<<1)) //尋址PCF8591,如未應(yīng)答,則停止操作并返回0
{
I2CStop();
return 0;
}
I2CWrite(0x40|chn); //寫入控制字節(jié),選擇轉(zhuǎn)換通道
I2CStart();
I2CWrite((0x48<<1)|0x01); //尋址PCF8591,指定后續(xù)為讀操作
I2CReadACK(); //先空讀一個字節(jié),提供采樣轉(zhuǎn)換時間
val = I2CReadNAK(); //讀取剛剛轉(zhuǎn)換完的值
I2CStop();
return val;
}
/* ADC轉(zhuǎn)換值轉(zhuǎn)為實際電壓值的字符串形式,str-字符串指針,val-AD轉(zhuǎn)換值 */
void ValueToString(unsigned char *str, unsigned char val)
{
//電壓值=轉(zhuǎn)換結(jié)果*2.5V/255,式中的25隱含了一位十進制小數(shù)
val = (val*25) / 255;
str[0] = (val/10) + '0'; //整數(shù)位字符
str[1] = '.'; //小數(shù)點
str[2] = (val%10) + '0'; //小數(shù)位字符
str[3] = 'V'; //電壓單位
str[4] = '\0'; //結(jié)束符
}
void ConfigTimer0(unsigned int ms)
{
unsigned long tmp; //臨時變量
tmp = 11059200 / 12; //定時器計數(shù)頻率
tmp = (tmp * ms) / 1000; //計算所需的計數(shù)值
tmp = 65536 - tmp; //計算定時器重載值
tmp = tmp + 12; //補償中斷響應(yīng)延時造成的誤差
T0RH = (unsigned char)(tmp>>8); //定時器重載值拆分為高低字節(jié)
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;
}
}
復(fù)制代碼
作者:
哈蘭德
時間:
2023-6-16 22:07
51單片機的模數(shù)和數(shù)模轉(zhuǎn)換,難以理解?
作者:
xuyaqi
時間:
2023-6-17 06:37
比如用傳感器測壓力,AD轉(zhuǎn)換出來的內(nèi)碼(val)并不是我們要的壓力值,要通過量程轉(zhuǎn)換變成真實的壓力值,這個25就是轉(zhuǎn)換系數(shù),要根據(jù)實際環(huán)境調(diào)整大小。
作者:
hcfat51h
時間:
2023-6-17 08:50
2.5/255=V取樣/val
V取樣=val*2.5/255, 換成用25*val是為了避免浮點運算
作者:
188610329
時間:
2023-6-17 17:15
你已經(jīng)知道,255是量程。
25則是 滿量程情況下的電壓值。大多基準(zhǔn)電壓都是2.5V.
你71行代碼中的注釋已經(jīng)寫的很清楚了:
//電壓值=轉(zhuǎn)換結(jié)果*2.5V/255,式中的25隱含了一位十進制小數(shù)
而72行的代碼,就是依據(jù)71行的注釋的具體實現(xiàn)。
作者:
rctty
時間:
2023-6-19 14:43
這就相當(dāng)于 y = kx + b
y 相當(dāng)于你的電壓
x 相當(dāng)于獲取的ADC
k 相當(dāng)于25/255
b 在這里為0
歡迎光臨 (http://www.torrancerestoration.com/bbs/)
Powered by Discuz! X3.1