附件里面有設計任務,根據附件原理圖改正里面的程序。完整的word文檔請在本文最后下載附件,下面是部分內容預覽:
0.png (69.01 KB, 下載次數: 110)
下載附件
2016-6-5 14:11 上傳
目 錄 一、原理 ……………………………………………………………………………………………1 二、硬件介紹 ………………………………………………………………………………………1 2.1 單片機介紹…………………………………………………………………………………1 2.2 AT24C02I2C數據存儲 ……………………………………………………………………2 2.3 PCF8591 A/D轉換 …………………………………………………………………………2 2.4 LCD1602 液晶顯示模塊……………………………………………………………………3 硬件連接及工作過程簡介………………………………………………………………………4 3.1 硬件連接……………………………………………………………………………………4 3.2 工作過程簡介………………………………………………………………………………5 三、工作流程圖 ……………………………………………………………………………………6 四、程序清單 ………………………………………………………………………………………7 五、PCB圖 …………………………………………………………………………………………18 六、總結……………………………………………………………………………………………18 八、參考文獻………………………………………………………………………………………19
一、原理本文所設計的是一種以單片機STC12C5A60S2(引腳排序及基本功能同AT89S51)作為主控芯片的雙通道電壓采集電路,將采集到的模擬信號電壓值利用PCF8591來進行模數轉換,PCF8591是一個單片集成、單獨供電、低功耗、8-bitCMOS數據獲取信號。其中PCF8591共有4個模擬輸入、一個模擬輸出和一個串行口I2C總線接口,通過PLCF8591將轉換成的數字信號電壓值傳給液晶顯示屏,并將所測電壓值在LCD1602液晶顯示屏中顯示出來,而且要利用AT24C04設置電壓上下限,在電壓超出上下限時顯示屏要有所表示.本文主要針對雙通道的數據采集與顯示,繼而推廣多通道數據采集的方法,重點分析介紹了基于AT89S51數字電壓采集的硬件設計和軟件設計。
0.png (229.93 KB, 下載次數: 131)
下載附件
2016-6-5 14:11 上傳
圖3-1硬件連接原理圖
0.png (64.61 KB, 下載次數: 106)
下載附件
2016-6-5 14:15 上傳
SDA、SCL是IIC數據線和時鐘線,可連接于單片機任何IO管腳在。在本次設計中通過芯片AT24C02來編寫所測電壓的上下限值。 我們這次試驗所測得電壓是直流電壓0至5伏是模擬信號由于我們所測得電壓要在 LCD1602 液晶顯示屏中顯示出來,但是LCD1602液晶顯示屏接受和表達數字信號,所以要用PCF8591 A/D轉換芯片把采集的模擬信號電壓值轉換成數值信號,經過AT89S51再把信號傳給LCD液晶顯示屏,最終在液晶顯示屏上顯示出電壓值。如果采集的電壓值在設定的電壓值之間,則電壓值能在液晶顯示屏上顯示出電壓,如果超出了則在液晶顯示屏上有所表示。在此次試驗中因為是雙通道采集電壓,所以我們測兩條電路的電壓,我在這兩條電路上各串聯了一個滑動變阻器,用來改變所測的電壓值。
五、程序清單 - #include "common.h"
- float v_low = 2.8; //電壓范圍下限
- float v_high = 4.5; //電壓范圍上限
- uchar BUF[2]; //從at24c04中讀取的數據存儲在這
- uchar w_buf[2]; //寫入at24c04中的數據存在這里
- //延時函數大約1ms
- void delay_ms(int ms)
- {
- int i;
- while(ms--)
- {
- for(i=0;i<100;i++);
- }
- }
- //連續寫入兩個數據
- void AT24C04_Write(uchar dat_1,uchar dat_2)
- {
- AT24C04_Start(); //起始信號
- AT24C04_SendByte(0xa0); //發送設備地址+寫信號
- AT24C04_SendByte(0x00); //發送存儲單元地址
- AT24C04_SendByte(dat_1); //寫入數據1
- AT24C04_SendByte(dat_2); //寫入數據2
- AT24C04_Stop(); //停止信號
- }
- //連續讀出兩個數據
- void AT24C04_ReadPage()
- {
- uchar i;
- AT24C04_Start(); //起始信號
- AT24C04_SendByte(0xa0); //發送設備地址+寫信號
- AT24C04_SendByte(0x00); //發送存儲單元地址
- AT24C04_Start(); //起始信號
- AT24C04_SendByte(0xa1); //發送設備地址+讀信號
- for (i=0; i<2; i++)
- {
- BUF[i] = AT24C04_RecvByte();
- if (i == 1)
- {
- AT24C04_SendACK(1); //最后一個數據需要會NAK
- }
- else
- {
- AT24C04_SendACK(0); //回應ACK
- }
- }
- AT24C04_Stop(); //停止信號
- }
- //LCD顯示數字處理函數
- void show_num(uchar num,uchar flag)
- {
- uchar temp[3],i;
- float re_val; //電壓實際值
- float read_low,read_h; //將從AT24C04中讀取電壓范圍數據轉化成對應小數形式
- re_val = num/255.0*5.0; //實際電壓計算公式
- num = re_val*10; //保留一位小數
- AT24C04_ReadPage();//從AT24C04中讀取電壓范圍數據,存儲在BUF數組中
- // BUF[0]表示下限,BUF[1]表示上限
- //存入AT24C04中的數據是uchar unsigned型,在這里轉化成float型
- read_low = BUF[0]/10.0;
- read_h = BUF[1]/10.0;
- if(re_val >= read_low && re_val <= read_h) //如果電壓在范圍內
- {
- temp[0] = num/10 + '0';
- temp[1] = '.';
- temp[2] = num%10 + '0';
- }else if(re_val < read_low ) //如果低于設定值
- {
- temp[0] = 'L';
- temp[1] = 'O';
- temp[2] = 'W';
- }else if(re_val > read_h ) //如果高于設定值
- {
- temp[0] = 'H';
- temp[1] = 'I';
- temp[2] = 'G';
- }
-
- for(i=0;i<3;i++) //用液晶顯示結果
- {
- LCD_Manifest(flag,3+i,temp[i]);
- }
- //顯示電壓范圍的上限
- num = read_h * 10;
- temp[0] = num/10 + '0';
- temp[1] = '.';
- temp[2] = num%10 + '0';
- for(i=0;i<3;i++) //用液晶顯示結果
- {
- LCD_Manifest(1,12+i,temp[i]);
- }
- //顯示電壓范圍的下限
- num = read_low * 10;
- temp[0] = num/10 + '0';
- temp[1] = '.';
- temp[2] = num%10 + '0';
- for(i=0;i<3;i++) //用液晶顯示結果
- {
- LCD_Manifest(2,12+i,temp[i]);
- }
- }
- //主函數
- void main()
- {
- uchar val; //電壓值
- LCD_Init(); //液晶初始化
- IIC_Init(); //I2C總線初始化
- w_buf[0] = v_low*10;
- w_buf[1] = v_high*10;
- AT24C04_Write(w_buf[0],w_buf[1]); //將數據寫入AT24C04
-
- LCD_Manifest(1,0,'V'); //在lcd1602中顯示字符
- LCD_Manifest(1,1,'1');
- LCD_Manifest(1,2,':');
- LCD_Manifest(2,0,'V');
- LCD_Manifest(2,1,'2');
- LCD_Manifest(2,2,':');
- LCD_Manifest(1,10,'H');
- LCD_Manifest(1,11,':');
- LCD_Manifest(2,10,'L');
- LCD_Manifest(2,11,':');
- while(1)
- {
- //按鍵檢測程序
- if(key_1 == 0) //調節范圍的下限
- {
- delay_ms(100); //延時消除抖動
- if(key_1 == 0)
- {
- // v_low = v_low - 0.1;
- // if(v_low < 0.0)
- // v_low = v_high;
- w_buf[0] = v_low*10;
- w_buf[1] = v_high*10;
- AT24C04_Write(w_buf[0],w_buf[1]); //將數據寫入AT24C04
- }
- }
- if(key_2 == 0) //調節范圍的上限
- {
- delay_ms(100); //延時消除抖動
- if(key_2 == 0)
- {
- v_high = v_high + 0.1;
- if(v_high > 5.0)
- v_high = v_low;
- w_buf[0] = v_low*10;
- w_buf[1] = v_high*10;
- AT24C04_Write(w_buf[0],w_buf[1]); //將數據寫入AT24C04
- }
- }
- ADC_Send_Byte(0x90,0x41);//通道一ADC轉換
- val=ADC_Receive_Byte(0x90); //讀取AD轉換的值
- show_num(val,1);
- ADC_Send_Byte(0x90,0x42);//通道二ADC轉換
- val=ADC_Receive_Byte(0x90); //讀取AD轉換的值
- show_num(val,2);
- }
- }
- #include<iic.h>
- void IIC_Init()//總線初始化
- {
-
- SCL=1;
- IIC_DELAY();
- SDA=1;
- IIC_DELAY();
- }
- void IIC_Start() //啟動信號
- {
-
- SDA=1;
- IIC_DELAY();
- SCL=1;
- IIC_DELAY();
- SDA=0;
- IIC_DELAY();
- }
- void IIC_Stop() //停止信號
- {
-
- SDA=0;
- IIC_DELAY();
- SCL=1;
- IIC_DELAY();
- SDA=1;
- IIC_DELAY();
- }
- void IIC_Ack() //應答信號
- {
- unsigned char i;
- SCL=1;
- IIC_DELAY();;
- while((SDA==1)&&(i<255))i++;
- SCL=0;
- IIC_DELAY();
- }
- void IIC_Write_Byte(u8 date)//寫一個字節
- {
- u8 i,temp;
- temp=date;
- for(i=0;i<8;i++)
- {
- temp=temp<<1;
- SCL=0;
- IIC_DELAY();
- SDA=CY;//最高位將移入PSW寄存器的CY位中,然后將CY賦給SDA
- IIC_DELAY();
- SCL=1;
- IIC_DELAY();
- }
- SCL=0;
- IIC_DELAY();
- SDA=1;
- IIC_DELAY();
- }
- u8 IIC_Read_Byte()//讀一個字節
- {
- u8 i,temp;
- for(i=0;i<8;i++)
- {
- SCL=0;
- IIC_DELAY();
- temp=(temp<<1)|SDA;
- IIC_DELAY();
- SCL=1;
- IIC_DELAY();
- }
- SCL=0;
- IIC_DELAY();
- SDA=1;
- IIC_DELAY();
- return temp;
- }
- #include <reg51.h>
- #include"lcd1602.h"
- void delay(u8 z)//延時函數
- {
- unsigned char x,y;
- for(x=z;x>0;x--)
- for(y=110;y>0;y--);
- }
- void LCD_Write_Cmd(u8 com )//液晶寫命令
- {
- LCD_RS=0;//選擇寫命令模式
- LCD_dat=com;//將要寫的命令字送到數據總線上
- delay(1);
- LCD_E=1;//使能端給一高脈沖,高脈沖有效
- delay(1);
- LCD_E=0;
- }
- void LCD_Write_Data(u8 date)//數據寫命令
- {
- LCD_RS=1;//選擇寫數據模式
- LCD_dat=date;
- delay(1);
- LCD_E=1;//使能端給一高脈沖,高脈沖有效
- delay(1);
- LCD_E=0;
- }
- void LCD_Init()//液晶初始化
- {
-
- LCD_WR=0;
- LCD_Write_Cmd(0x38);//設置16*2顯示,5*7點陣,8位數據接口
- LCD_Write_Cmd(0x0c);//設置開顯示,不顯示光標
- LCD_Write_Cmd(0x06);//寫一個字符后地址指針自動加1
- LCD_Write_Cmd(0x80);//數據指針定位到第一行第一個字處
- }
- // 使得寫命令和寫數據通過一個函數完成
- void LCD_Manifest(u8 row,u8 add,u8 date)
- {
- if(row==1) LCD_Write_Cmd(0x80+add);
- if(row==2) LCD_Write_Cmd(0xc0+add);
- LCD_Write_Data(date);
- }
- #include"iic.h"
- #include"pcf8591.h"
- //ADC發送字節[命令]數據函數
- void ADC_Send_Byte(u8 addr,u8 com)
- {
- IIC_Start(); //啟動總線
- IIC_Write_Byte(addr); //發送器件地址
- IIC_Ack();
- IIC_Write_Byte(com); //發送數據
- IIC_Ack();
- IIC_Stop(); //結束總線
- }
- //ADC讀字節數據函數
- u8 ADC_Receive_Byte(u8 addr)
- {
- u8 c;
- IIC_Start(); //啟動總線
- IIC_Write_Byte(addr+1); //發送器件地址,如果是讀則最低位為1即0x91
- IIC_Ack();
- c=IIC_Read_Byte(); //讀取數據
- IIC_Ack(); //發送非就答位
- IIC_Stop(); //結束總線
- return(c);
- }
- #include"AT24C04.h"
- void Delay5us()
- {
- BYTE n = 4;
- while (n--)
- {
- _nop_();
- _nop_();
- }
- }
- void Delay5ms()
- {
- WORD n = 2500;
- while (n--)
- {
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- }
- }
- void AT24C04_Start()
- {
- AT_SDA = 1; //拉高數據線
- AT_SCL = 1; //拉高時鐘線
- Delay5us(); //延時
- AT_SDA = 0; //產生下降沿
- Delay5us(); //延時
- AT_SCL = 0; //拉低時鐘線
- }
- void AT24C04_Stop()
- {
- AT_SDA = 0; //拉低數據線
- AT_SCL = 1; //拉高時鐘線
- Delay5us(); //延時
- AT_SDA = 1; //產生上升沿
- Delay5us(); //延時
- }
- void AT24C04_SendACK(bit ack)
- {
- AT_SDA = ack; //寫應答信號
- AT_SCL = 1; //拉高時鐘線
- Delay5us(); //延時
- AT_SCL = 0; //拉低時鐘線
- Delay5us(); //延時
- }
- bit AT24C04_RecvACK()
- {
- AT_SCL = 1; //拉高時鐘線
- Delay5us(); //延時
- CY = AT_SDA; //讀應答信號
- AT_SCL = 0; //拉低時鐘線
- Delay5us(); //延時
- return CY;
- }
- void AT24C04_SendByte(BYTE dat)
- {
- BYTE i;
- for (i=0; i<8; i++) //8位計數器
- {
- dat <<= 1; //移出數據的最高位
- AT_SDA = CY; //送數據口
- AT_SCL = 1; //拉高時鐘線
- Delay5us(); //延時
- AT_SCL = 0; //拉低時鐘線
- Delay5us(); //延時
- }
- AT24C04_RecvACK();
- }
- BYTE AT24C04_RecvByte()
- {
- BYTE i;
- BYTE dat = 0;
- AT_SDA = 1; //使能內部上拉,準備讀取數據
- for (i=0; i<8; i++) //8位計數器
- {
- dat <<= 1;
- AT_SCL = 1; //拉高時鐘線
- Delay5us(); //延時
- dat |= AT_SDA; //讀數據
- AT_SCL = 0; //拉低時鐘線
- Delay5us(); //延時
- }
- return dat;
- }
復制代碼
0.png (135.75 KB, 下載次數: 121)
下載附件
2016-6-5 14:13 上傳
七、總結 本次課程設計,我學到了很多的東西,對匯編語言程序設計加深了理解和掌握,我們這次設計的要求主要是熟悉微型計算機技術中所學到的幾中芯片的使用,掌握它們的初始化編程,并學會他們的基本應用,這是一個比較全面的設計,和以前的實驗相比較復雜很多,一方面要求我們設計硬件電路,另一方面需要對設計的硬件電路進行編程,這就需要軟件和硬件相結合,具體的電路具體分析,在此次設計中還用到了AT24C02芯片,在此次之前我們從沒用到這個芯片,對這個芯片非常陌生,而且網上也沒有什么系統的解釋,和AT89S51的管腳的連線也不清楚,但是最后通過不停地調試,最后還是被解決了。通過這次課程設計后,我對學硬件有了一定的體會,它要求我們認真仔細的做好每個環節,對所有的問題要考慮周全,它和軟件不同,對具體的電路要編寫適合該電路的程序,電路一改,程序也要跟著改,從中我也學會了很多實際應用的知識。通過本次設計,我才發現我所學的東西的膚淺,知識面的不牢固,在選擇方案的時候,產生模棱兩可的情況。經常是邊設計邊復習學習過的課本知識。這些使我知道“紙上談兵”是絕對不行,只有通過實踐,自己親自動手試一試,才能發現自己知識的缺陷,才能更好的與所學的知識相結合。在課程設計中我們每個人都能學到很多,有很大的收獲。做任何事情所要有的態度和心態,首先我明白了做學問要一絲不茍,對于出現的任何問題和偏差都不要輕視,要通過正確的途徑去解決,在做事情的過程中要有耐心和毅力,不要一遇到困難就打退堂鼓,只要堅持下去就可以找到思路去解決問題的。在工作中要學會與人合作的態度,認真聽取別人的意見,這樣做起事情來就可以事倍功半。
課程設計任務書下載:
任務書10----雙通道電壓采集電路設計(LCD顯示).doc
(36.5 KB, 下載次數: 19)
2016-6-5 11:07 上傳
點擊文件名下載附件
設計任務 下載積分: 黑幣 -5
完整的設計文檔下載:
單片機課設.doc
(214.5 KB, 下載次數: 49)
2016-6-5 11:14 上傳
點擊文件名下載附件
根據里面的設計原理圖寫程序 下載積分: 黑幣 -5
|