|
發(fā)布時(shí)間: 2016-4-13 14:13
正文摘要:想做個(gè)PM2.5檢測(cè)儀,夏普的傳感器也已經(jīng)購(gòu)得,隨即做了一塊ATMEGA329P的最小系統(tǒng)版如圖: |
![]() ![]() ![]() ![]() 很不錯(cuò)的樣子 |
|
本帖最后由 yjx189 于 2016-4-16 11:05 編輯 上面的代碼中,傳感器使用了A0和D2口,但是這個(gè)D2口1602屏也要使用,怎么才能避開呢? 還有就是,也沒有看到初始化1602屏的語(yǔ)句啊? |
baofu 發(fā)表于 2016-4-15 18:38 有時(shí)間的話,還請(qǐng)你幫我看看下面的源代碼,可以用嗎?費(fèi)心了,朋友! PM2.5檢測(cè)器 代碼如下: int measurePin = 0; // 連接模擬口0 int ledPower = 2; // 連接數(shù)字口2 int samplingTime = 280; int deltaTime = 40; int sleepTime = 9680; float voMeasured = 0; float calcVoltage = 0; float dustDensity = 0; void setup(){ Serial.begin(9600); pinMode(ledPower,OUTPUT); } void loop(){ digitalWrite(ledPower,LOW); //開啟內(nèi)部LED delayMicroseconds(samplingTime); // 開啟LED后的280us的等待時(shí)間 voMeasured = analogRead(measurePin); // 讀取模擬值 delayMicroseconds(deltaTime); // 40us等待時(shí)間 digitalWrite(ledPower,HIGH); // 關(guān)閉LED delayMicroseconds(sleepTime); // 0 - 5V mapped to 0 - 1023 integer values // recover voltage calcVoltage = voMeasured * (5.0 / 1024.0); //將模擬值轉(zhuǎn)換為電壓值 dustDensity = 0.17 * calcVoltage - 0.1; //將電壓值轉(zhuǎn)換為粉塵密度輸出單位 Serial.print(“Raw Signal Value (0-1023): ”); Serial.print(voMeasured); Serial.print(“ - Voltage: ”); Serial.print(calcVoltage); Serial.print(“ - Dust Density: ”); Serial.println(dustDensity); // 輸出單位: 毫克/立方米 delay(1000); } |
baofu 發(fā)表于 2016-4-15 18:38 再一次表示感謝!但我弄半天還是不行!都有些煩了,過兩天再說吧,再不行,就找個(gè)做程序員的朋友幫我寫一個(gè)吧! |
| 怎么感覺這個(gè)電路很簡(jiǎn)單 |
yjx189 發(fā)表于 2016-4-15 08:05 30樓的函數(shù)digitalWrite()由于你沒有貼出來函數(shù)體。只能說31樓的代碼,這個(gè)應(yīng)當(dāng)是正確的,唯一不足就是init()函數(shù)中的: LCD_write_command(0x38); // - - 設(shè)置8位格式,2行,5x7 LCD_delay_10us(5); 只有一次寫入0x38,如果這一次失敗,往下就不行了。應(yīng)當(dāng)重復(fù)延時(shí)多次才可靠。我記得這是文檔上特意說明的, 問題是為什么非得這樣才可靠?我估計(jì)是1602控制器里面由于某種原因,反應(yīng)太慢,需要多次重復(fù)才能建立穩(wěn)定狀態(tài)。純屬臆測(cè),未必正確。 除了上述不同,與我貼出的代碼很接近,而我實(shí)驗(yàn)是成功的,你用這個(gè)如果還不行,就應(yīng)當(dāng)從別處找問題了。 |
|
這個(gè)也寫進(jìn)去過: # define LCD_DB P0 // - - P0 = DB0~DB7 sbit LCD_RS=P2^0; // - - p2.0 = RS sbit LCD_RW=P2^1; // - - p2.1 = RW sbit LCD_E=P2^2; // - - p2.2 = E // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - 定義函數(shù) # define uchar unsigned char # define uint unsigned int // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - 定義子程序函數(shù) void LCD_init(void); // - - 初始化LCD1602函數(shù) void LCD_write_command(uchar command); // - - 向LCD1602寫指令函數(shù) void LCD_write_data(uchar dat); // - - 向LCD1602寫數(shù)據(jù)函數(shù) void LCD_set_xy(uchar x,uchar y); // - - 設(shè)置LCD1602顯示位置 X(0-16),y(1-2) void LCD_disp_char(uchar x,uchar y,uchar dat); // - - 在LCD1602上顯示一個(gè)字符 void LCD_disp_string(uchar X,uchar Y,uchar *s); // - - 在LCD1602上顯示一個(gè)字符串 //void LCD_check_busy(void);//檢查忙函數(shù)。我沒用到此函數(shù),因?yàn)橥ㄟ^率極低。 void LCD_delay_10us(uint n); // - - 10微秒的延時(shí)子程序 void LCD_delay_50us(uint n); // - - 50微秒的延時(shí)子程序 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - 初始化LCD1602 void LCD_init(void) { LCD_delay_10us(20); LCD_write_command(0x38); // - - 設(shè)置8位格式,2行,5x7 LCD_delay_10us(5); LCD_write_command(0x0c); // - - 整體顯示,關(guān)光標(biāo),不閃爍 LCD_delay_10us(5); LCD_write_command(0x06); // - - 設(shè)定輸入方式,增量不移位 LCD_delay_10us(5); LCD_write_command(0x01); // - - 清除屏幕顯示 LCD_delay_50us(40); } //******************************** // - - 向LCD1602寫指令 void LCD_write_command(uchar dat) { LCD_delay_10us(5); LCD_RS=0; // - - 指令 LCD_RW=0; // - - 寫入 LCD_DB=dat; LCD_delay_10us(5); LCD_E=1; // - - 允許 LCD_delay_10us(5); LCD_E=0; } // - - 向LCD1602寫數(shù)據(jù) void LCD_write_data(uchar dat) { LCD_delay_10us(5); LCD_RS=1;// - - 數(shù)據(jù) LCD_RW=0;// - - 寫入 LCD_DB=dat; LCD_delay_10us(5); LCD_E=1;// - - 允許 LCD_delay_10us(5); LCD_E=0; } // - - 設(shè)置顯示位置 void LCD_set_xy(uchar x,uchar y) { uchar address; if(y==1) { address=0x80+x; // - - 第一行位置 } else { address=0xc0+x; // - - 第二行位置 } LCD_delay_10us(5); LCD_write_command(address); } // - - 顯示一個(gè)字符函數(shù) void LCD_disp_char(uchar x,uchar y,uchar dat) // - - LCD_disp_char(0,1,0x38); // - - 顯示8 { LCD_set_xy(x,y); LCD_delay_10us(5); LCD_write_data(dat); } // - - 顯示一個(gè)字符串函數(shù) void LCD_disp_string(uchar x,uchar y,uchar *s) { LCD_set_xy(x,y); LCD_delay_10us(5); while(*s!='\0') { LCD_write_data(*s); s++; } } //******************************** /*******檢查忙函數(shù)************* void LCD_check_busy() //實(shí)踐證明,在我的LCD1602上,檢查忙指令通過率極低,以 { //至于不能正常使用LCD。因此我沒有再用檢查忙函數(shù)。而使 do //用了延時(shí)的方法,延時(shí)還是非常好用的。我試了一下,用 { LCD_E=0; //for循環(huán)作延時(shí),普通指令只要1次循就可完成。清屏指令 LCD_RS=0; //要用200次循環(huán)便能完成。 LCD_RW=1; LCD_DB=0xff; LCD_E=1; }while(LCD_DB^7==1); } void LCD_delay_10us(uint n) // - - 10微秒的延時(shí)子程序 { uint i,j; for(i=n;i>0;i--) for(j=2;j>0;j--); } void LCD_delay_50us(uint n) // - - 50微秒的延時(shí)子程序 { uint i,j; for(i=n;i>0;i--) for(j=22;j>0;j--); } |
baofu 發(fā)表于 2016-4-14 19:53 謝謝你的熱心幫助!我的寫的代碼如下(在網(wǎng)上搜到的),有空請(qǐng)幫我找找問題! int LCD1602_RS=12; int LCD1602_RW=11; int LCD1602_EN=10; int DB[] = { 6, 7, 8, 9}; char logtxt[]="Local Time"; char *sec[60]={"00","01","02","03","04","05","06","07","08","09","10","11","12","13","14","15","16","17","18","19","20","21","22","23","24","25","26","27","28","29","30","31","32","33","34","35","36","37","38","39","40","41","42","43","44","45","46","47","48","49","50","51","52","53","54","55","56","57","58","59"}; void LCD_Command_Write(int command) { int i,temp; digitalWrite( LCD1602_RS,LOW); digitalWrite( LCD1602_RW,LOW); digitalWrite( LCD1602_EN,LOW); temp=command & 0xf0; for (i=DB[0]; i <= 9; i++) { digitalWrite(i,temp & 0x80); temp <<= 1; } digitalWrite( LCD1602_EN,HIGH); delayMicroseconds(1); digitalWrite( LCD1602_EN,LOW); temp=(command & 0x0f)<<4; for (i=DB[0]; i <= 9; i++) { digitalWrite(i,temp & 0x80); temp <<= 1; } digitalWrite( LCD1602_EN,HIGH); delayMicroseconds(1); digitalWrite( LCD1602_EN,LOW); } void LCD_Data_Write(int dat) { int i=0,temp; digitalWrite( LCD1602_RS,HIGH); digitalWrite( LCD1602_RW,LOW); digitalWrite( LCD1602_EN,LOW); temp=dat & 0xf0; for (i=DB[0]; i <= 9; i++) { digitalWrite(i,temp & 0x80); temp <<= 1; } digitalWrite( LCD1602_EN,HIGH); delayMicroseconds(1); digitalWrite( LCD1602_EN,LOW); temp=(dat & 0x0f)<<4; for (i=DB[0]; i <= 9; i++) { digitalWrite(i,temp & 0x80); temp <<= 1; } digitalWrite( LCD1602_EN,HIGH); delayMicroseconds(1); digitalWrite( LCD1602_EN,LOW); } void LCD_SET_XY( int x, int y ) { int address; if (y ==0) address = 0x80 + x; else address = 0xC0 + x; LCD_Command_Write(address); } void LCD_Write_Char( int x,int y,int dat) { LCD_SET_XY( x, y ); LCD_Data_Write(dat); } void LCD_Write_String(int X,int Y,char *s) { LCD_SET_XY( X, Y ); //設(shè)置地址 while (*s) //寫字符串 { LCD_Data_Write(*s); s ++; } } void setup (void) { int i = 0; for (i=6; i <= 12; i++) { pinMode(i,OUTPUT); } delay(100); LCD_Command_Write(0x28);//4線 2行 5x7 delay(50); LCD_Command_Write(0x06); delay(50); LCD_Command_Write(0x0c); delay(50); LCD_Command_Write(0x80); delay(50); LCD_Command_Write(0x01); delay(50); } void loop (void) { for(int index=0,minindex=59,hourindex=12;index<60;index++) //這里來設(shè)定現(xiàn)在時(shí)間,目前設(shè)定為12:59:00 { LCD_Command_Write(0x01); delay(50); LCD_Write_String(3,0,logtxt); LCD_Write_String(3,1,sec[hourindex]); LCD_Write_Char(6,1,0x3a);//顯示: LCD_Write_String(7,1,sec[minindex]); LCD_Write_Char(10,1,0x3a); LCD_Write_String(11,1,sec[index]); delay(950); if (index==59) { index=-1; minindex++; if (minindex==60) { minindex=0; hourindex++; if (hourindex==24) { hourindex=0; } } } } } |
Action 發(fā)表于 2016-4-14 14:20 我郵箱,yjx189@sohu.com,謝謝! |
|
本帖最后由 baofu 于 2016-4-14 20:01 編輯 我用的單片機(jī)與你不一樣,管腳什么都不一致,HEX文件給你也無法用。比較合適的辦法是你把你的初始化部分的代碼貼在這里,大家共同找找問題。我的代碼很簡(jiǎn)單: void LCD_init() { LCD_delay_50us(20); LCD_RS=0; // - - 指令 LCD_RW=0; // - - 寫入 LCD_E=0; // - - 使能 LCD_write_L4bit_command(0x38); //寫0x38 LCD_delay_50us(2); //延時(shí) LCD_write_L4bit_command(0x38); //重復(fù)寫 LCD_delay_50us(10); //延時(shí) LCD_write_L4bit_command(0x38); // 重復(fù)寫 LCD_delay_50us(5); 延時(shí) LCD_write_L4bit_command(0x38); // LCD_delay_50us(10); //可靠的初始化主要就是上面幾行 LCD_write_L4bit_command(0x02); // LCD_delay_50us(2); LCD_write_4bit_command(0x28); // - - LCD_delay_10us(10); LCD_write_4bit_command(0x0c); // - - 整體顯示,關(guān)光標(biāo),不閃爍 LCD_delay_10us(10); LCD_write_4bit_command(0x06); // - - 設(shè)定輸入方式,增量不移位 LCD_delay_10us(10); LCD_write_4bit_command(0x01); // - - 清除屏幕顯示 LCD_delay_50us(40); } |
不懂 幫頂 |
| 給我郵箱 我給你發(fā)程序 你這個(gè)的主要原因是 需要把vee接到滑動(dòng)變阻器的滑動(dòng)腳 滑動(dòng)變阻器其他兩個(gè)腳接電源跟地 調(diào)節(jié)滑動(dòng)變阻器就可以了 |
| 第三個(gè)問題,可以用定時(shí) |
| 看看大神如何解決 |
| 我已經(jīng)用單片機(jī)往1602里寫了,但還是那樣,問題還是沒得到解決! |
| 網(wǎng)上看看1602的歷程,對(duì)比看看 |
本帖最后由 yjx189 于 2016-4-14 08:14 編輯 baofu 發(fā)表于 2016-4-14 08:02 |
baofu 發(fā)表于 2016-4-13 20:01 能否把你寫的初始化程序給我復(fù)制一份,我參考一下使用?謝謝了! |
yjx189 發(fā)表于 2016-4-13 21:40 1602自己不能接受寫入程序,也寫不進(jìn)去,只能用單片機(jī)對(duì)1602進(jìn)行寫命令或?qū)憯?shù)據(jù)。 |
| 不是往1602里面寫程序,它也不能接收。1602只能與單片機(jī)之間交換數(shù)據(jù)。初始化也是單片機(jī)對(duì)1602操作才能完成。 |
|
1602里面主要是液晶點(diǎn)陣,這些點(diǎn)陣受控制器的指揮,而控制器又受單片機(jī)的指揮。單片機(jī)對(duì)控制器只有三種操作:查忙;寫命令;寫數(shù)據(jù);所有的這些都是單片機(jī)對(duì)1602的操作,所以不用往1602寫程序,也寫不進(jìn)去。 查忙:控制器工作比單片機(jī)慢,操作前先查忙,答復(fù)有空閑才能真的操作。為了簡(jiǎn)單,往往就用延時(shí)取代了。 寫命令:所有的命令都是十六進(jìn)制數(shù),具體含義要查廠方的文檔。比如上述寫0x38,是設(shè)置顯示模式命令。 寫數(shù)據(jù):寫入要顯示的內(nèi)容。 |
wc86110 發(fā)表于 2016-4-13 22:41 明白了,謝謝!我正在網(wǎng)上找有關(guān)資料,學(xué)習(xí)燒寫1602初始化函數(shù)的問題! |
| 是往目標(biāo)單片機(jī)里燒寫程序而非往1602。 |
本帖最后由 yjx189 于 2016-4-13 21:41 編輯 baofu 發(fā)表于 2016-4-13 21:15 UNO是Arduino UNO開發(fā)板(相當(dāng)于51單片機(jī)的開發(fā)板,這個(gè)我也有) 的簡(jiǎn)稱,我是在UNO板上寫好了程序,把寫好程序的芯片拿下來(相當(dāng)于單片機(jī)的STC89C52),做了一個(gè)最小系統(tǒng)板,一邊接上v,傳感器,做一個(gè)PM2.5的檢測(cè)儀! 不過,上面說了,我也有STC89C52的開發(fā)板,可以寫程序,要往1602里面寫程序,是不是就是通過89C52的開發(fā)板(插上1602屏)往里面寫初始化的程序? |
|
本帖最后由 yjx189 于 2016-4-14 10:05 編輯 UNO是Arduino UNO開發(fā)板(相當(dāng)于51單片機(jī)的開發(fā)板,這個(gè)我也有) 的簡(jiǎn)稱,我是在UNO板上寫好了程序,把寫好程序的芯片拿下來(比如單片機(jī)的STC89C52),做了一個(gè)最小系統(tǒng)板,接上1602屏,傳感器,做一個(gè)PM2.5的檢測(cè)儀! |
|
具體對(duì)1602的操作函數(shù),網(wǎng)上可以查到很多例子。 你說的UNO板子,我確實(shí)不熟悉。 從你說的看,像是自己又做了一個(gè)板子?如果你自己做的板子是模仿UNO而不成功,則可能你自制的板子有問題。 |
本帖最后由 yjx189 于 2016-4-15 07:20 編輯 baofu 發(fā)表于 2016-4-13 20:27 本帖最后由 yjx189 于 2016-4-13 20:35 編輯 請(qǐng)問: 怎么往1602里面寫東西啊?在一個(gè)是:為什么我的1602和寫好程序的ATMEGA328P芯片,在UNO板上,就都一切正常,到了我做的ATMEGA328P芯片小系統(tǒng)上,就都不正常了呢? |
|
本帖最后由 yjx189 于 2016-4-14 08:06 編輯 請(qǐng)問: 怎么往1602里面寫東西啊?在一個(gè)是:為什么我的1602和寫好程序的ATMEGA328P芯片,在UNO板上,就都一切正常,到了我做的ATMEGA328P芯片消息同伴上,就都不正常了呢? |
| 就是往1602寫0x38,實(shí)際就是寫設(shè)置顯示模式的命令(注意模式不同,命令不一樣),關(guān)鍵是多重復(fù)幾次,且每次之間延時(shí)就行了。 |
本帖最后由 yjx189 于 2016-4-13 20:21 編輯 baofu 發(fā)表于 2016-4-13 20:01 估計(jì)就是你說的初始化的問題了!那請(qǐng)問:0X38要往哪里面寫?怎么寫呢?請(qǐng)明示,多謝了。▽(shí)在不好意思!我學(xué)單片機(jī)也就才20天,大學(xué)的專業(yè)也是汽車,不是電) |
baofu 發(fā)表于 2016-4-13 20:01 我是個(gè)小白,哈哈,學(xué)單片機(jī)也就才20天,并且大學(xué)的專業(yè)也是汽車,請(qǐng)問,是要上電前,先找個(gè)1602的初始化的程序,寫進(jìn)ATMEGA329P的芯片里嗎? |
|
主要是上電后一開始就執(zhí)行置顯示模式命令(我的是寫入0x38),至少要重復(fù)4次,且每次之間加1ms到5ms的延時(shí)(用延時(shí)就不再查詢忙否了),我的實(shí)踐證明,這很關(guān)鍵。 但平臺(tái)硬件都不同,只能供你參考。 |
本帖最后由 yjx189 于 2016-4-13 19:47 編輯 baofu 發(fā)表于 2016-4-13 15:15 謝謝回復(fù)!電源是穩(wěn)壓供電5V。那請(qǐng)問:初始化不合適,怎么操作,就能合適了呢? |
|
我用stc12c5410ad單片機(jī)驅(qū)動(dòng)1602,也有過類似于你遇到的這種情況。 1.顯示方框不顯示文字,基本上是兩種原因:第一種是對(duì)比度調(diào)整不當(dāng),在我的屏上,就是1602的V0管腳電壓不合適;你的已經(jīng)正常顯示過,這個(gè)可以排除。第二種是管腳接觸不良,我用杜邦線連接,很容易出現(xiàn)連接不可靠,動(dòng)動(dòng)連接線就好了。 2.顯示內(nèi)容不對(duì),且字符自動(dòng)移動(dòng)。這個(gè)多數(shù)是對(duì)1602的初始化不合適或者“忙”處理不當(dāng)所致。特別是當(dāng)給1602供電的電源偏低的時(shí)候,往往會(huì)導(dǎo)致1602初始化失敗。 由于硬件不同,僅供參考。 |
|
現(xiàn)在的現(xiàn)象是: 一,把ATMEGA328P芯片寫入“點(diǎn)亮一盞燈”程序,在相當(dāng)于UNO板的13腳的引腳接上LED和電阻,LED閃爍正常。 二,寫入“歡迎,,,,,”程序,有時(shí)1602屏能正常顯示“歡迎,,”的英文,有時(shí)則只顯示兩行灰色的方塊。 三,寫入“簡(jiǎn)單時(shí)鐘電路”程序,1602屏兩行亂碼,并且隨著時(shí)鐘的秒的節(jié)奏,從屏左面向平右面滾動(dòng)。 四,換其他的1602屏插上,情況一樣。這兩個(gè)程序的芯片,插在UNO板子上,都顯示正常。 請(qǐng)問各位高手,這是什么問題?怎樣解決? |
Powered by 單片機(jī)教程網(wǎng)