为了让后来者少走弯路,分享一个51单片机AD四路采集PCF8591实时采集的例程。双IIC接口,还附上Proteus防真。
地址:AD四路采集串口显示双IIC
单片机源程序如下:
- #include "main.h"
- // 变量定义
- u32 V0=0,V1=0,V2=0,V3=0;
- u8 num;
- //******************************************************************/
- main()
- {
- OLED_Init();
- OLED_ColorTurn(0); //0正常显示,1 反色显示
- OLED_DisplayTurn(0); //0正常显示 1 屏幕翻转显示
- OLED_DrawBMP(0,0,128,64,BMP1);
-
- Uart_Init();
- Timer0_Init();
-
- delayms(500);
- OLED_Clear();
-
- OLED_ShowChinese(24,1,0,16);//祝
- OLED_ShowChinese(40,1,1,16);//你
- OLED_ShowChinese(56,1,2,16);//好
- OLED_ShowChinese(72,1,3,16);//运
- OLED_ShowChinese(88,1,4,16);//!
- delayms(500);
- OLED_Clear();
-
- OLED_ShowString(0,0,"CHANNEL1:",16);
- OLED_ShowString(0,2,"CHANNEL2:",16);
- OLED_ShowString(0,4,"CHANNEL3:",16);
- OLED_ShowString(0,6,"CHANNEL4:",16);
-
- while(1)
- {
- if(num==10)
- {
- V0=ADC(0x40);
- delayms(10);
- V1=ADC(0x41);
- delayms(10);
- V2=ADC(0x42);
- delayms(10);
- V3=ADC(0x43);
- delayms(10);
- DAC(V1);
- delayms(10);
-
- UartPrintASCII(V0);
- delayms(2);
- UartPrintASCII(V1);
- delayms(2);
- UartPrintASCII(V2);
- delayms(2);
- UartPrintASCII(V3);
- UartPrintf("OK !");
-
- V0=V0*50000/255;
- V1=V1*50000/255;
- V2=V2*50000/255;
- V3=V3*50000/255;
-
- num=0;
-
- OLED_ShowNum(80,0,V1/10000,1,16);
- OLED_ShowString(88,0,".",16);
- OLED_ShowNum(96,0,V1%10000,4,16);
-
- OLED_ShowNum(80,2,V2/10000,1,16);
- OLED_ShowString(88,2,".",16);
- OLED_ShowNum(96,2,V2%10000,4,16);
-
- OLED_ShowNum(80,4,V3/10000,1,16);
- OLED_ShowString(88,4,".",16);
- OLED_ShowNum(96,4,V3%10000,4,16);
-
- OLED_ShowNum(80,6,V0/10000,1,16);
- OLED_ShowString(88,6,".",16);
- OLED_ShowNum(96,6,V0%10000,4,16);
-
- }
-
- }
- }
- //*******************************************************************
- void Timer0_Isr() interrupt 1
- {
- TF0 = 0; /*清除中断标志*/
- TR0 = 0; /*关中断*/
-
- num++;
-
- TL0 = 0x00; //设置定时初始值
- TH0 = 0x4C; //设置定时初始值
- TR0 = 1; /*开中断*/
- }
- //*******************************************************************
复制代码
- #include "ADC.h"
- //*****串口初始化函数***********
- //******************************
- void Uart_Init(void)
- {
- REN = 1; //允许串行口接收数据
- PCON &= 0x7F; //波特率不倍速
- SCON = 0x50; //8位数据,可变波特率
- AUXR &= 0xBF; //定时器时钟12T模式
- AUXR &= 0xFE; //串口1选择定时器1为波特率发生器
- TMOD &= 0x0F; //设置定时器模式
- TMOD |= 0x20; //设置定时器模式
- TL1 = 0xFD; //设置定时初始值
- TH1 = 0xFD; //设置定时重载值
- EA = 1; //打开全局中断控制
- ES = 0; //打开串行口中断
- ET1 = 0; //禁止定时器中断
- TR1 = 1; //定时器1开始计时
- }
- void UartPrintASCII(u8 dat) //发送一个字符
- {
- TI=0;
- SBUF=dat;
- while(TI==0);
- TI=0;
- }
- void UartPrintf(u8 *p) //发送字符串
- {
- while(*p)
- {
- SBUF=*(p++);
- while(TI==0)
- {
- };
- TI=0;
- }
- }
- void Timer0_Init(void) //50毫秒@11.0592MHz
- {
- EA=1;
- ET0 = 1; /*允许定时中断*/
- TMOD &= 0xF0; //设置定时器模式
- TMOD |= 0x01; //设置定时器模式
- TL0 = 0x00; //设置定时初始值
- TH0 = 0x4C; //设置定时初始值
- TR0 = 1; /*启动定时中断*/
- }
- /*******************************************************************
- 起动总线函数
- 函数原型: void IIcStart();
- 功能: 启动I2C总线,即发送I2C起始条件.
- ********************************************************************/
- void IIcStart()
- {
- SCL=1;
- SDA=1; /*发送起始条件的数据信号*/
- delay5us();
- SDA=0; /*发送起始信号*/
- delay5us();
- }
- /*******************************************************************
- 结束总线函数
- 函数原型: void IIcStop();
- 功能: 结束I2C总线,即发送I2C结束条件.
- ********************************************************************/
- void IIcStop()
- {
- SCL=1 ;
- SDA=0; /*发送结束条件的数据信号*/
- delay5us();
- SDA=1; /*发送I2C总线结束信号*/
- delay5us();
- }
- /********************************************************************
- 发送应答
- 函数原型: IIc_ACK(bit a);
- 功能: 主控器进行应答信号(注意:0表示发送应答,1表示发送非应答)
- ********************************************************************/
- void IIc_Ack(bit ack)
- {
- SCL=1;
- delay5us();
- SDA=ack; /*清时钟线,钳住I2C总线以便继续接收*/
- delay5us();
- SCL=0;
- }
- /********************************************************************
- 等待应答
- 函数原型: IIc_WaitACK(void);
- 功能: 主控器进行应答信号(0是就帮答)
- ********************************************************************/
- bit IIc_WaitAck(void)
- {
- SCL=0;
- delay5us();
- SCL=1;
- delay5us();
- if(SDA==1)
- {
- SCL=0;
- return 0;
- }
- else
- {
- SCL=0;
- return 1;
- }
- }
- /*******************************************************************
- 字节数据发送函数
- 函数原型: void SendByte(UCHAR c);
- 功能: 将数据c发送出去,可以是地址,也可以是数据,发完后等待应答,并对
- 此状态位进行操作.(不应答或非应答都使ack=0)
- 发送数据正常,ack=1; ack=0表示被控器无应答或损坏。
- ********************************************************************/
- void SendByte(unsigned char date)
- {
- unsigned char temp,i; //用于探测字节内某一位值的掩码变量
- temp=date;
- for (i=0; i<8; i++) //从高位到低位依次进行
- {
- temp=temp<<1;
- SCL=0 ;
- delay5us();
- SDA = CY;
- delay5us();
- SCL = 1; //拉高SCL
- delay5us();
- }
- SCL = 0;
- SDA = 1; //8位数据发送完后,主机释放SDA,以检测从机应答
- }
- /*******************************************************************
- 字节数据接收函数
- 函数原型: UCHAR RcvByte();
- 功能: 用来接收从器件传来的数据,并判断总线错误(不发应答信号),
- 发完后请用应答函数应答从机。
- ********************************************************************/
- unsigned char RcvByte(void)
- {
- unsigned char i,j,k;
- SCL=0;
- delay5us();
- for(i=0;i<8;i++)
- {
- SCL=1;
- delay5us();
- j=SDA;
- k=(k<<1)|j;
- SCL=0;
- delay5us();
- }
- return k;
- }
- /*******************************************************************
- D/A 变换, 转化函数
- *******************************************************************/
- void DAC(unsigned char dat)
- {
- IIcStart(); //启动总线
- SendByte(0x90); //发送器件地址0x90是写,0x91是读
- IIc_WaitAck();
- SendByte(0x41); //发送控制字节//允许DA输出
- IIc_WaitAck();
- SendByte(dat); //发送DAC的数值
- IIc_WaitAck();
- IIcStop(); //结束总线
- }
- /*******************************************************************
- ADC读字节数据函数
- *******************************************************************/
- unsigned char ADC(unsigned char addr)
- {
- unsigned char temp;
- IIcStart(); //启动总线
- SendByte(0x90); //发送器件地址0x90是写,0x91是读
- IIc_WaitAck();
- SendByte(addr); //控制字节:选择光敏电阻(0x41)还是滑动变阻器(0x43
- IIc_WaitAck();
- IIcStart();
- SendByte(0x91);
- IIc_WaitAck();
- temp=RcvByte();
- IIc_Ack(1); //0表示发送应答,1表示发送非应答
- IIcStop();
- return temp;
- }
复制代码 Proteus8.15版本的仿真:
Proteus8.15版本的仿真.7z
(133.22 KB, 下载次数: 50)
|