這是一個把PCF8591-4個通道都開啟的AD采集,OLED12864顯示.單片機:STC15W408AS
通道1:光敏電阻--光照強度0-100(自己定義的),根據采集的AD值轉換成光照梯度
通道2:熱敏電阻--NTC,通過采集出來的AD值轉換成溫度值。
通道3,4:通過電位器采集電源電壓
這段時間在用PCF8591AD采集模塊,發送只采集一個通道時,AD采集是正常的,但是當把4個通道都開啟時,就要出錯,通過查資料才發送一些問題。關于PCF8591說明,自己用8591作AD采集時,當只用一個通道時,
都能采集出正常的AD值,但是把4個通道都開啟時,就會出錯,通過查資料得知,PCF8591,發送AD轉轉指令時,
得到的是上一次的AD值,如果設置通道號自動增加的話,當發送采集通道2AD值的指令時,實際讀取的AD值時
通道1的AD值,所以要重復發送同一通道的AD采集指令,保證采集到的AD值是要采集用到的AD值。
RJ5[7X(_%4$~]DN5)S}JCNO.jpg (2.74 MB, 下載次數: 70)
下載附件
OLED12864顯示4個通道
2020-5-17 13:18 上傳
XJ]05CR5S)S(`MEM~MH78A2.jpg (2.47 MB, 下載次數: 61)
下載附件
PCB
2020-5-17 13:18 上傳
單片機源程序如下:
- /******************************************************************************************
- PCF8591-4通道AD采集,OLED12864顯示
- 通道1:光敏電阻--光照強度0-100(自己定義的),根據采集的AD值轉換成光照梯度
- 通道2:熱敏電阻--NTC,通過采集出來的AD值轉換成溫度值。
- 通道3,4:通過電位器采集電源電壓
- 關于PCF8591說明,自己用8591作AD采集時,當只用一個通道時,都能采集出正常的AD值,但是把4
- 個通道都開啟時,就會出錯,通過查資料得知,PCF8591,發送AD轉轉指令時,得到的是上一次的AD值,
- 如果設置通道號自動增加的話,當發送采集通道2AD值的指令時,實際讀取的AD值時通道1的AD值,所以
- 要重復發送同一通道的AD采集指令,保證采集到的AD值是要采集用到的AD值
- ******************************************************************************************/
- #include "OLED.h"
- #include "PCF8591.h"
- #include "math.h"
- float Vin; //采集的電壓
- float Rt; //電阻阻值
- float temper;
- u8 TableBuff1[]="000CD";
- u8 TableBuff2[]="000.0C";
- u8 TableBuff3[]="0.00V";
- void Time0_Init(u8 T0XMS,u8 Mode)
- {
- u16 T0_xMS; //定時器T0的初值變量,現定義10ms 的初值,注意要與FOSC統一單位標準
- if(Mode == 0) TMOD &= 0xF0; //設置定時器模式0 16位自動重轉
- if(Mode == 1) {TMOD&= 0XF0;TMOD|=0X01;}
- if(Mode == 2) {TMOD&= 0XF0;TMOD|=0X02;}
- if(Mode == 3) {TMOD&= 0XF0;TMOD|=0X03;}
- //=====裝載初值
- #ifdef T0_1T //1T模式
- T0_xMS =(65536-T0XMS*FOSC/1000); //FOSC的定義在 STC8.H中
- #else //12T模式
- T0_xMS =(65536-T0XMS*FOSC/12/1000);
- #endif
- TL0 = T0_xMS;
- TH0 = T0_xMS >> 8;
- TR0 = 1;
- ET0 = 1;
- EA = 1;
- }
- u8 AD_CH=1;
- void main()
- {
- u16 value;
- u16 valuet;
- u16 temp=123;
- IIC_int();
- Time0_Init(20,0);
- OLED_Init();
- Write_GB16X16(0,0,"CH0:");
- Write_GB16X16(2,0,"CH1:");
- Write_GB16X16(4,0,"CH2:");
- Write_GB16X16(6,0,"CH3:");
- while(1)
- {
- switch(AD_CH)
- {
- case 0: //光明電阻
- value=ReadPCF_Dat(0X40); //這事獲得的AD值是通道4的AD值
- value=ReadPCF_Dat(0X40); //多采集幾次,保證是通道0的AD值
- value=ReadPCF_Dat(0X40);
- value=ReadPCF_Dat(0X40);
- value = 100-(value*100.0/255.0);
-
- TableBuff1[0] = value%1000/100 +0X30;
- TableBuff1[1] = value%100/10 +0X30;
- TableBuff1[2] = value%10 +0X30;
- Write_GB16X16(0,4,TableBuff1);
- break;
- case 1: //熱敏電阻
- value=ReadPCF_Dat(0X41);
- value=ReadPCF_Dat(0X41);
- value=ReadPCF_Dat(0X41);
- value=ReadPCF_Dat(0X41);
- Vin = ( 5*value )/255.0;
- Rt = 10*Vin/(5-Vin);
-
- temper = ( (3950 *298.15)/( (298.15 * log (Rt / 10)) + 3950 ) )-273.15;
- valuet = temper*10;
-
- TableBuff2[0] = valuet%10000/1000 +0X30;
- TableBuff2[1] = valuet%1000/100 +0X30;
- TableBuff2[2] = valuet%100/10 +0X30;
-
- TableBuff2[4] = valuet%10 +0X30;
-
- Write_GB16X16(2,4,TableBuff2);
- break;
- case 2: //測電壓
- value=ReadPCF_Dat(0X42);
- value=ReadPCF_Dat(0X42);
- value=ReadPCF_Dat(0X42);
- value=ReadPCF_Dat(0X42);
- value = 500.0*value/255.0;
- TableBuff3[0] = value%1000/100 +0X30;
- TableBuff3[2] = value%100/10 +0X30;
- TableBuff3[3] = value%10 +0X30;
- Write_GB16X16(4,4,TableBuff3);
- break;
- case 3: //測電壓
- value=ReadPCF_Dat(0X43);
- value=ReadPCF_Dat(0X43);
- value=ReadPCF_Dat(0X43);
- value=ReadPCF_Dat(0X43);
- value = 500.0*value/255.0;
- TableBuff3[0] = value%1000/100 +0X30;
- TableBuff3[2] = value%100/10 +0X30;
- TableBuff3[3] = value%10 +0X30;
- Write_GB16X16(6,4,TableBuff3);
- break;
- }
- }
- }
- u8 a=0;
- void Time0() interrupt 1
- {
- a++;
- if(a>25)
- {
- a=0;
- AD_CH++;
- if(AD_CH>3)AD_CH=0; //通過定時器改變要采集的通道
- }
- }
復制代碼- #include "OLED.h"
- #include "Font.h"
- void Delay_OLED(u16 t)
- {
- u16 i,j;
- for(i=t;i>0;i--)
- for(j=500;j>0;j--);
- }
- /***********向SSD1306寫一字節數據***********
- Dat:要寫入的數據/命令
- Cmd:數據/命令標志 0,表示命令;1,表示數據;
- ********************************************/
- void Write_OLED_Byte(u8 Dat,u8 Cmd)
- {
- u8 i;
- OLED_CS = 0;
- OLED_DC =Cmd;
- for(i=0;i<8;i++)
- {
- OLED_SCL = 0;
- OLED_SDA = Dat&0X80;
- OLED_SCL = 1;
- Dat<<=1;
- }
- OLED_CS = 1;
- }
- /*********設置顯示坐標*********/
- void OLED_Set_PoS(u8 page,u8 column)
- {
- Write_OLED_Byte(0XB0+page,OLED_CMD);
- Write_OLED_Byte( ((column&0XF0)>>4)|0X10,OLED_CMD);
- Write_OLED_Byte( column&0X0F,OLED_CMD);
- }
- ////開啟OLED顯示
- //void OLED_Display_On(void)
- //{
- // Write_OLED_Byte(0X8D,OLED_CMD); //SET DCDC命令
- // Write_OLED_Byte(0X14,OLED_CMD); //DCDC ON
- // Write_OLED_Byte(0XAF,OLED_CMD); //DISPLAY ON
- //}
- ////關閉OLED顯示
- //void OLED_Display_Off(void)
- //{
- // Write_OLED_Byte(0X8D,OLED_CMD); //SET DCDC命令
- // Write_OLED_Byte(0X10,OLED_CMD); //DCDC OFF
- // Write_OLED_Byte(0XAE,OLED_CMD); //DISPLAY OFF
- //}
- /************操作整個屏幕************
- Input: Ins=0 清除整個屏幕
- Ins=0XFF 全部顯示整個屏幕
- *************************************/
- void OLED_Screen_All(u8 Ins)
- {
- u8 page,seg;
- for(page=0;page<8;page++)
- {
- OLED_Set_PoS(page,0);
- for(seg=0;seg<128;seg++)
- Write_OLED_Byte(Ins,OLED_DAT);
- }
- }
- ///*********OLED初始化***********/
- //void OOLED_INIT()
- //{
- ////--復位
- // OLED_RST = 1;
- // Delay_OLED(200);
- // OLED_RST = 0;
- // Delay_OLED(200);
- // OLED_RST = 1;
- // Delay_OLED(20);
- ////--指令初始化
- //}
- /*********OLED初始化***********/
- void OLED_Init()
- {
- OLED_RST = 1;
- Delay_OLED(200);
- OLED_RST = 0;
- Delay_OLED(200);
- OLED_RST = 1;
- Delay_OLED(20);
- //--地址設置
- Write_OLED_Byte(0X20,OLED_CMD); //設置尋址模式
- Write_OLED_Byte(0X02,OLED_CMD); //0X00--水平尋址;0X01--垂直尋址;0X02--頁面尋址
- //--硬件設置
- //顯示方向-引腳向上為正方向
- Write_OLED_Byte(0XA1,OLED_CMD); //段尋址,add0-->seg0
- Write_OLED_Byte(0XC8,OLED_CMD); //com掃描方向,com0-com63
- //引腳在下為正方向
- //Write_OLED_Byte(0XA0,OLED_CMD); //段尋址,add127-->seg0
- //Write_OLED_Byte(0XC0,OLED_CMD); //com掃描方向,com63-com0
- Write_OLED_Byte(0X8D,OLED_CMD); //電荷泵設置
- Write_OLED_Byte(0X14,OLED_CMD); //REST=0X10, 0X14才能顯示內容
- //--基本命令
- Write_OLED_Byte(0X81,OLED_CMD); //設置對比度
- Write_OLED_Byte(0XCF,OLED_CMD); //0X00-0XFF,與數值成正比 RES=0X7F
- Write_OLED_Byte(0XA4,OLED_CMD); //整體顯示開啟,可用來測試液晶是否顯示正常
- //0XA4跟隨RAM內容,0XA5不跟隨RAM的內容,一直是白屏全部顯示。
- Write_OLED_Byte(0XA6,OLED_CMD); //設置正顯0XA6,反顯0XA7
- Write_OLED_Byte(0XAF,OLED_CMD); //0XAE顯示關,0XAF顯示開
- //---清屏
- OLED_Screen_All(0);
- }
- /**************清除N個8*16區域**********/
- //void Clear8X16(u8 page, u8 column ,u8 N)
- //{
- // u8 i,j,k;
- // column*=8;
- // for(k=0;k<N;k++)
- // {
- // for(i=0;i<2;i++)
- // {
- // OLED_Set_PoS(page+i,column+k*8);
- // for(j=8;j>0;j--)
- // Write_OLED_Byte(0X00,OLED_DAT);
- // }
- // }
- //}
- /*****************在(16行/2頁)*Wide列區域寫數據****************
- Input:
- *Buff@點陣數據 Num@字符個數,Wide@字體寬度
- Wide=8時,為寫8*16的數據,字母,符號
- Wide=16時,為寫宋體2號漢字
- **************************************************************/
- void Write_16xWide(u8 page,u8 column ,u8 *Buff,u8 Num,u8 Wide)
- {
- u8 i,j,k;
- for(k=0;k<Num;k++)
- {
- for(i=0;i<2;i++)
- {
- OLED_Set_PoS(page+i,column+k*8);
- for(j=Wide;j>0;j--)
- {
- Write_OLED_Byte(*Buff,OLED_DAT);
- Buff++;
- }
- }
- }
- }
- /**************寫宋體12號漢字 16*Wide ***********
- Input: page@頁 column@列 *CH@字符串
- 可以顯示漢字,數字,字母,符號
- page:0 2 4 6 column:0~15
- ************************************************/
- void Write_GB16X16(u8 page,u8 column ,u8 *CH)
- {
- u8 a,k;
- if( (*CH>=0X20) && (*CH<=0X7E) ) column=column;
- else column*=8;
- while( *CH != '\0')
- {
- if( (*CH>=0X20) && (*CH<=0X7E) ) //數字,字母,符號 一行16個
- {
- k=*CH-0X20;
- for(a=0;a<2;a++)
- {
- Write_16xWide(page,column*8, &ASCII_8X16[k][0],1,8);
- }
- CH+=1;
- column+=1;
- }
- else //漢字,一行 8個
- {
- for(a=0;a<FontNum;a++)
- {
- if( (*CH == GB12Hanzi[a].Index[0]) && (*(CH+1)==GB12Hanzi[a].Index[1]) )
- Write_16xWide(page,column,&GB12Hanzi[a].Msk[0],1,16);
- }
- CH+=2;
- column+=16;
- }
- }
- }
復制代碼
51hei.png (4.12 KB, 下載次數: 61)
下載附件
2020-5-17 14:59 上傳
全部資料51hei下載地址:
PCF8591.zip
(1.37 MB, 下載次數: 78)
2020-5-17 13:19 上傳
點擊文件名下載附件
程序,PCF原理圖,手冊 下載積分: 黑幣 -5
|