熱門: 51單片機(jī) | 24小時(shí)必答區(qū) | 單片機(jī)教程 | 單片機(jī)DIY制作 | STM32 | Cortex M3 | 模數(shù)電子 | 電子DIY制作 | 音響/功放 | 拆機(jī)樂(lè)園 | Arduino | 嵌入式OS | 程序設(shè)計(jì)
|
發(fā)布時(shí)間: 2018-5-17 13:26
正文摘要:1)為什么我IO口初始的電壓不是為0,而是0.9V到1.3V來(lái)回跳動(dòng)? 2)我實(shí)際測(cè)得電壓也不準(zhǔn)確,測(cè)不到3V以下的電壓。 我是通過(guò)電阻分壓的方法,將需要測(cè)量的電壓進(jìn)行分壓,然后直接接到對(duì)應(yīng)的IO口去,這樣應(yīng)該是沒(méi) ... |
哈哈007 發(fā)表于 2018-5-17 13:27 LCD模塊數(shù)據(jù)不對(duì) |
| 因?yàn)殡妷耗K焊錯(cuò)了 |
| 我就看看大神 |
哈哈007 發(fā)表于 2018-5-20 14:46 由于使用的單片機(jī)和實(shí)驗(yàn)板電路不同,改動(dòng)部分都有注釋。 //使用單片機(jī)型號(hào):IAP15W4K58S4,1T 使用內(nèi)部時(shí)鐘11.0592MHz #include <STC15F2K60S2.H> //STC15系列通用頭文件 //#include "reg52.h" #include "intrins.h" typedef unsigned char uchar; typedef unsigned int uint; #define _Nop() _nop_() /*------------------------以下為L(zhǎng)CD1602顯示模塊定義-----------------------*/ unsigned char data_char_table[]= {"0123456789ABCDEF"};//LCD數(shù)據(jù) unsigned char Lcd_Dis1_table[] = {"Position:No. "};//第一行顯示框架 unsigned char pos_char_table[] = {" D "};// 顯示位置 unsigned char Lcd_Dis2_table[] = {"Voltage : V"};//第二行顯示框架 unsigned char num_char_table[] = {" 9A.CD V"};// 顯示位置 #define lcd_data_port P0 //sbit lcd_rs_port = P2^4; //定義LCD控制端口,根據(jù)硬件調(diào)整 //sbit lcd_rw_port = P2^3; //sbit lcd_en_port = P2^2; sbit lcd_rs_port = P3^5; //定義LCD控制端口,根據(jù)硬件調(diào)整 //sbit lcd_rw_port = P2^3;//實(shí)驗(yàn)板固定接地,不使用讀功能 sbit lcd_en_port = P3^4; sbit LEDa=P2^5; //573LED使能端口 sbit dula=P2^6; //573數(shù)碼管段使能端口 sbit wela=P2^7; //573數(shù)碼管位使能端口 void lcd_delay(uchar ms); //LCD1602 延時(shí) //void lcd_busy_wait(); //LCD1602 忙等待 void lcd_command_write(uint command);//LCD1602 命令字寫入 void lcd_system_reset(); //LCD1602 初始化 void lcd_char_write(uint x_pos,y_pos,lcd_dat);//LCD1602 字符寫入 //void lcd_bad_check();//LCD1602 壞點(diǎn)檢查 void Num_to_Disp(uchar i, uint Num);//顯示數(shù)據(jù)處理 void LcdDisp(uchar j, uint num);//液晶顯示函數(shù) /*------------------------以下為ADC相應(yīng)寄存器初始化及端口定義-------------*/ /***** 定義與ADC相關(guān)的特殊功能寄存器 *****/ /* 與STC15頭文件內(nèi)容重復(fù) sfr ADC_CONTR = 0xBC; //ADC控制寄存器 sfr ADC_RES = 0xBD; //ADC hight 8-bit result register sfr ADC_RESL = 0xBE; //ADC low 2-bit result register sfr P1ASF = 0x9D; //P1口功能控制寄存器P1ASF sfr P1M0 = 0x92; //I/O模式寄存器 sfr P1M1 = 0x91; //I/O模式寄存器*/ /************定義相應(yīng)操作位***************/ #define ADC_POWER 0x80 //ADC電源控制位,0:關(guān)閉,1:打開(kāi) #define ADC_FLAG 0x10 //ADC結(jié)束標(biāo)志位 #define ADC_START 0x08 //ADC啟動(dòng)控制位 #define ADC_SPEEDLL 0x00 //540 clocks___________選擇轉(zhuǎn)換速度 /*------------------------以下為相關(guān)函數(shù)聲明------------------------------*/ void InitADC(); //ADC初始化 uint GetADCResult(uchar ch); void Delay(uint n); //延時(shí)程序 void delay_1ms(uchar x); uint shuju=0; /*---------------------------- 初始化ADC特殊功能寄存器 -------------------*/ void InitADC( ) { P1ASF = 0xff; //Set P1.0 - P1.7 as analog input port ADC_RES = 0; //Clear previous result ADC_RESL = 0; ADC_CONTR = ADC_POWER | ADC_SPEEDLL ; Delay(20); //ADC power-on delay and Start A/D conversion } /*-------------------------------- ADC 取值 ------------------------------*/ uint GetADCResult(uchar ch) { ADC_CONTR=0x88|ch; //開(kāi)啟AD轉(zhuǎn)換1000 1000 即POWER SPEED1 SPEED0 ADC_FLAG ADC_START CHS2 CHS1 CHS0 _nop_(); _nop_(); _nop_(); _nop_();//要經(jīng)過(guò)4個(gè)CPU時(shí)鐘的延時(shí),其值才能夠保證被設(shè)置進(jìn)ADC_CONTR 寄存器 // ADC_RES=0xdf; // ADC_RESL=0xef; while(!(ADC_CONTR&0x10)); //等待轉(zhuǎn)換完成 ADC_CONTR&=0xe7; //關(guān)閉AD轉(zhuǎn)換,ADC_FLAG位由軟件清0 return(ADC_RES*4+ADC_RESL); //返回AD轉(zhuǎn)換完成的10位數(shù)據(jù)(16進(jìn)制) } /*---------------------------- LCD1602相應(yīng)函數(shù) ---------------------------*/ //////////////以下是LCD1602驅(qū)動(dòng)程序//////////////// void lcd_delay(uchar ms)//1ms延時(shí)(11.0592MHz 1T) { uint i,j; for(i=ms;i>0;i--) for(j=1150;j>0;j--); } /* void lcd_delay(uchar ms) //LCD1602 延時(shí) { uchar j; while(ms--) for(j=0;j<250;j++); }*/ /* //實(shí)驗(yàn)板不使用讀功能,用延時(shí)代替查忙 void lcd_busy_wait() //LCD1602 忙等待 { lcd_rs_port = 0; // lcd_rw_port = 1; lcd_en_port = 1; lcd_data_port = 0xff; while (lcd_data_port&0x80); lcd_en_port = 0; }*/ void lcd_command_write(uint command) /*LCD1602 命令字寫入*/ { // lcd_busy_wait(); lcd_rs_port = 0; // lcd_rw_port = 0; lcd_en_port = 0; lcd_data_port = command; lcd_delay(1); lcd_en_port = 1; lcd_delay(1); lcd_en_port = 0; } void lcd_system_reset() /*LCD1602 初始化*/ { dula=0; //關(guān)閉數(shù)碼管段選 wela=0; //關(guān)閉數(shù)碼管位選 LEDa=0; //關(guān)閉LED使能 // lcd_delay(20); // lcd_command_write(0x38); // lcd_delay(100); // lcd_command_write(0x38); // lcd_delay(50); lcd_command_write(0x38); // lcd_delay(10); lcd_command_write(0x08); lcd_command_write(0x01); lcd_command_write(0x06); lcd_command_write(0x0c); } void lcd_char_write(uint x_pos,y_pos,lcd_dat) /*LCD1602 字符寫入*/ { x_pos &= 0x0f; /* X位置范圍 0~15 */ y_pos &= 0x01; /* Y位置范圍 0~ 1 */ if(y_pos==1) x_pos += 0x40; x_pos += 0x80; lcd_command_write(x_pos); // lcd_busy_wait(); lcd_rs_port = 1; // lcd_rw_port = 0; // lcd_en_port = 0; lcd_data_port = lcd_dat; lcd_delay(1); lcd_en_port = 1; lcd_delay(1); lcd_en_port = 0; } /* void lcd_bad_check() //LCD1602 壞點(diǎn)檢查 { char i,j; for(i=0;i<2;i++){ for(j=0;j<16;j++) { lcd_char_write(j,i,0xff); } } lcd_delay(200); lcd_delay(200); lcd_delay(200); lcd_delay(100); lcd_delay(200); lcd_command_write(0x01); // clear lcd disp }*/ //////////////////以上是LCD1602驅(qū)動(dòng)程序//////////////// /*----------------------------- 延時(shí)程序 ---------------------------*/ void Delay(uint n) { uint x; while (n--) { x = 500; while (x--); } } /*1MS為單位的延時(shí)程序*/ void delay_1ms(uchar x) { uchar j; while(x--) { for(j=0;j<125;j++) {;} } } /***************************************************************** 函數(shù): averageValueVolgate() 用途: 求多次采集電壓平均值 傳入?yún)?shù):chan是端口號(hào) 返回值:Val_Av是多次采樣的電壓值平均值 ******************************************************************/ float averageValueVolgate(uchar chan) { float voltageValue=0; uchar num; for(num=100;num>0;num--) { voltageValue+=GetADCResult(chan); } voltageValue/=100.0; voltageValue=voltageValue;//*5.0/1024; return (voltageValue); } ///////////////以下為L(zhǎng)CD顯示數(shù)據(jù)處理///////////////// void Num_to_Disp(uchar i, uint Num) { float NUM; int xx, yy, zz; NUM = ((Num * 5 + 5) / 1024.0); //計(jì)算公式:10-bit A/D Conversion Result = 1024 x (Vin / Vcc) xx = (int)NUM; yy = (int)((NUM - (float)(xx)) * 10); zz = (int)((NUM - (float)(xx)) * 100)%10; num_char_table[9] = data_char_table[xx / 10]; //電壓值十位 num_char_table[10]= data_char_table[xx % 10]; //電壓值個(gè)位 num_char_table[12]= data_char_table[yy]; //電壓值小數(shù)點(diǎn)后一位 num_char_table[13]= data_char_table[zz]; //電壓值小數(shù)點(diǎn)后兩位 pos_char_table[13]= data_char_table; //當(dāng)前ADC接口 } //////////////////以下為L(zhǎng)CD顯示//////////////////// void LcdDisp(uchar j, uint num) { uint i=0; // for (i=0;i<16;i++) //此段代碼轉(zhuǎn)移到主函數(shù)初始化部分 // { // lcd_char_write(i,0,Lcd_Dis1_table); // lcd_char_write(i,1,Lcd_Dis2_table); //顯示框架 // } Num_to_Disp(j, num); lcd_char_write(13,0,pos_char_table[13]); //顯示當(dāng)前ADC接口 for(i = 9; i < 14; i++) { lcd_char_write(i,1,num_char_table); //顯示當(dāng)前電壓 } delay_1ms(100); } /*-------------------------------- 主函數(shù) --------------------------------*/ void main() { uchar i; //此段端口配置屬IAP15W4K58S4所需,全部為準(zhǔn)雙向口。 P0M0 = 0x00; P0M1 = 0x00; P1M1 = 0x00; P1M0 = 0x00; P2M0 = 0x00; P2M1 = 0x00; P3M0 = 0x00; P3M1 = 0x00; P4M0 = 0x00; P4M1 = 0x00; P5M0 = 0x00; P5M1 = 0x00; P6M0 = 0x00; P6M1 = 0x00; P7M0 = 0x00; P7M1 = 0x00; lcd_system_reset(); //LCD1602 初始化 // lcd_bad_check(); //LCD1602 壞點(diǎn)檢查 P1M1 = 0xFF; //P1.0~P1.7高阻 1111 1111 P1M0 = 0x00; //P1.0~P1.7高阻 0000 0000 InitADC(); //初始化ADC特殊功能寄存器 for (i=0;i<16;i++) { lcd_char_write(i,0,Lcd_Dis1_table); lcd_char_write(i,1,Lcd_Dis2_table); //顯示框架 } i=0; while (1) { LcdDisp(i,averageValueVolgate(i)); //液晶1602輪流顯示第0~7通道電壓值 i++; if(i>7) i=0; Delay(2000); } } |
wulin 發(fā)表于 2018-5-19 19:21 我用的是單片機(jī)最小的系統(tǒng),其他的什么都沒(méi)接,能不能把你修改后的程序發(fā)給我看看,我看下是我電路有問(wèn)題還是程序有問(wèn)題,拜托了 ![]() ![]() ![]() |
哈哈007 發(fā)表于 2018-5-19 16:36 讀取范圍0~VCC。如果還有問(wèn)題你要檢查硬件電路。 |
wulin 發(fā)表于 2018-5-19 07:07 但是這個(gè)不是讀取不了2.8V以下的電壓了嗎? |
哈哈007 發(fā)表于 2018-5-18 21:49 你這是簡(jiǎn)單的ADC轉(zhuǎn)換,要求不能太高。如果使用定時(shí)器,每20ms取樣10或20次(環(huán)境中的50Hz共/差模干擾周期),去掉一個(gè)最大和最小數(shù),其他數(shù)相加后+5(四舍五入算法),取平均值,可以做到很穩(wěn)定。想絕對(duì)穩(wěn)定什么方法都做不到。 |
wulin 發(fā)表于 2018-5-18 15:10 程序是什么啊,要咋改 |
哈哈007 發(fā)表于 2018-5-17 21:19 你重復(fù)計(jì)算:NUM =(Num * 5/ 1024.0); voltageValue=voltageValue*5.0/1024; 并且注釋掉了 P1M0 = 0x00; P1M1 = 0xFF; 這是在7通道用兩個(gè)1K電阻分壓VCC的測(cè)量結(jié)果
|
|
重復(fù)計(jì)算當(dāng)然出錯(cuò) NUM =(Num * 5/ 1024.0); voltageValue=voltageValue*5.0/1024; |
wulin 發(fā)表于 2018-5-17 17:23 你好 我這樣改以后電壓穩(wěn)定了,初始的電壓也為0,就是現(xiàn)在讀不了AD,一讀才0.01,是怎么回事,能幫我看下嘛?
|
wulin 發(fā)表于 2018-5-17 17:23
如果我想把這段濾波程序加進(jìn)去要怎么加? |
哈哈007 發(fā)表于 2018-5-17 16:57 如果只測(cè)某1個(gè)通道電壓:例如第3通道 void main() { uchar i; lcd_system_reset(); //LCD1602 初始化 lcd_bad_check(); //LCD1602 壞點(diǎn)檢查 InitADC(); //初始化ADC特殊功能寄存器 P1M1 = 0x3f; //P1.0/P1.5高阻 0011 1111 P1M0 = 0x00; //P1.0/P1.5高阻 0000 0000 while (1) { i = 2; LcdDisp(i, GetADCResult(i)); //液晶1602顯示第3通道電壓值 Delay(1000); } } |
|
你這個(gè)問(wèn)題,要看你的電路原理圖啊,只有程序是看不懂的。 因?yàn)槟愕倪@個(gè)程序,明顯是根據(jù)電路來(lái)寫的,還是個(gè)比較獨(dú)特的電路,不是一般常見(jiàn)的電路,所以,看不到電路,就無(wú)法回答你的問(wèn)題。 同時(shí),你也可以看你的電路啊,在沒(méi)有按鍵時(shí),P3口是個(gè)什么狀態(tài),就可以知道還原值了。 |
| 你這個(gè)問(wèn)題,要看你的電路原理圖啊,只有程序是看不懂的。 因?yàn)槟愕倪@個(gè)程序,明顯是根據(jù)電路來(lái)寫的,還是個(gè)比較獨(dú)特的電路,不是一般常見(jiàn)的電路,所以,看不到電路,就無(wú)法回答你的問(wèn)題。 同時(shí),你也可以看你的電路啊,在沒(méi)有按鍵時(shí),P3口是個(gè)什么狀態(tài),就可以知道還原值了。 |
wulin 發(fā)表于 2018-5-17 16:48 我就想要讓一個(gè)通道讀取AD就好了,不想那么多通道來(lái)回讀取 |
哈哈007 發(fā)表于 2018-5-17 13:27 你使用了我在前面回貼的錯(cuò)誤設(shè)置,原貼已編輯修正如下 /*-------------------------------- 主函數(shù) --------------------------------*/ void main() { uchar i; P1M1 = 0x3f; //P1.0~P1.5高阻 0011 1111 P1M0 = 0x00; //P1.0~P1.5高阻 0000 0000 主循環(huán)while (1)里 i = 2; while(i < 7)與P1.0~P1.5設(shè)為ADC不符。i 的值是0~5. |
這是我的程序,能幫忙看下有什么問(wèn)題嗎?
|
Powered by 單片機(jī)教程網(wǎng)