使用proteus,8051單片機,與pcf8591進行ad轉換
仿真原理圖如下(proteus仿真工程文件可到本帖附件中下載)
09-34-16-forum.jpg (440.93 KB, 下載次數: 78)
下載附件
2019-10-29 09:41 上傳
單片機源程序如下:
- #include<reg52.h>
- #define uint unsigned int
- #define uchar unsigned char
- sbit sda=P2^0; //自定義由普通IO口模擬I2C
- sbit scl=P2^1;
- sbit dm=P2^6; //段鎖存
- sbit wm=P2^7;
- uchar code table[]={0x3f,0x06,0x5b,0x4f,
- 0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
- void Delay(uint n)
- {
- uint i,j;
- for(i=n;i>0;i--)
- for(j=110;j>0;j--);
- }
- void delay() //延時幾微秒。延時函數在很多函數里都要用它。至少要大于4.7us
- {;;} //當你把這個函數寫在用它這個函數的前面就不用聲明了
- void init() //初始化總線。將總線都拉高以釋放
- {
- scl=1;
- delay(); //I2C總線使用時一般都要延時5us左右
- sda=1;
- delay();
- }
- void start() //啟始信號。 時鐘信號為高電平期間,數據總線產生下降沿。
- { //為什么要下降沿,且sda先要為1。因為先要保證數據線為空才能工作
- sda=1; //先釋放數據總線。高電平釋放
- delay();
- scl=1;
- delay();
- sda=0;
- delay();
- }
- void stop()
- {
- sda=0; //先要有工作狀態才能釋放,sda=0時在工作狀態
- delay();
- scl=1;
- delay();
- sda=1; //釋放數據總線
- delay();
- }
- void respons() //應答函數
- {
- uchar i=0;
- scl=1; //每個字節發送完后的第九個時鐘信號的開始
- delay();
- while((sda==1)&&(i<255)) //此處i的定義使用了uchar.只要填一個小于255的就行
- i++; //此處的sda是從機的
- scl=0; //表示主器件默認從器件已經收到而不再等待。不再等待之后,時鐘的高電平過了就是低電平,所以scl=0
- //此時第酒個時鐘信號結束
- }
- void writebyte(uchar d) //寫一字節,每次左移一位
- {
- uchar i,temp;
- temp=d;
- for(i=0;i<8;i++)
- {
- temp=temp<<1;
- scl=0; //數據傳輸期間要想sda可變,先把時鐘拉低。此處要給sda賦值
- delay();
- sda=CY; //CY為左移移入PSW寄存器中的的CY位。
- delay();
- scl=1; //sda有數據了。保持數據穩定
- delay();
- }
- scl=0; //此處是寫數據,是屬于數據傳輸過程中。只有在時鐘信號為低電平期間
- delay(); //數據總線才可以變化。
- sda=1; //所以要想釋放數據總線,就必須先把時鐘拉低
- delay();
- /*此處釋放總線寫在末尾是因為調用它時,前面有起始函數釋放了總線*/
- }
- uchar readbyte()
- {
- uchar i,k;
- scl=0;
- delay();
- sda=1;
- delay();
- /*此處釋放總線放在前面是因為一般都是先寫后讀,保險起見,釋放一下總線*/
- for(i=0;i<8;i++)
- {
- scl=1; //一個時鐘信號的開始
- delay();
- k=(k<<1)|sda; //實質是把sda的數據,最先傳來的放在最高位,依次往下排
- scl=0; //一個時鐘信號結束
- delay();
- }
- return k;
- }
- void display(uchar bai,uchar shi,uchar ge)
- {
- dm=1;
- P0=table[bai]; //顯示第一位
- dm=0;
- P0=0xff; //消隱
- wm=1;
- P0=0xfe;
- wm=0;
- P0=0x00; //消除仿真亂碼
- Delay(5);
-
- dm=1;
- P0=table[shi]; //顯示第二位
- dm=0;
- P0=0xff; //消隱
- wm=1;
- P0=0xfd;
- wm=0;
- P0=0x00; //消除仿真亂碼
- Delay(5);
-
- dm=1;
- P0=table[ge]; //顯示第三位
- dm=0;
- P0=0xff; //消隱
- wm=1;
- P0=0xfb;
- wm=0;
- P0=0x00; //消除仿真亂碼
- Delay(5);
- }
- /*void write(uchar addr,uchar dat)
- {
- start(); //初始化
- writebyte(0x90); //調用寫一字節函數.PCF8591為1001。此處是給從機發送寫信號(最低位是0)
- respons(); //調用應答函數讓從機應答
- writebyte(addr); //寫入地址
- respons(); //每寫一字節都要應答
- writebyte(dat);
- respons();
- stop();
- }*/
- uchar read(uchar addr)
- {
- uchar dat;
- start();
- writebyte(0x90); //從此處的發送地址和方向位0到從機
- respons(); //此處的從機產生應答。屬于“偽寫”。用于確定和哪臺機子通信
- writebyte(addr);
- respons();
- start();
- writebyte(0x91); //從此處開始,從機向主機寫數據。讀的方向位為1
- respons();
- dat=readbyte();
- stop();
- return dat; //讀得的數據要返回
- }
- void main()
- {
- uchar ge,shi,bai,n;
- init();
- while(1)
- {
- n=read(0x00); //此處是讀取內存的不同位置。至于從哪兒開始應該沒要求
- ge=n%10;
- shi=n%100/10;
- bai=n/100;
- display(bai,shi,ge);
- }
- }
復制代碼
所有資料51hei提供下載:
AD轉換.zip
(27.18 KB, 下載次數: 219)
2019-10-29 09:42 上傳
點擊文件名下載附件
源文件 下載積分: 黑幣 -5
|