标题:
51单片机AD四路采集串口显示双IIC及OLED显示
[打印本页]
作者:
KJYOU
时间:
2023-11-6 14:51
标题:
51单片机AD四路采集串口显示双IIC及OLED显示
为了让后来者少走弯路,分享一个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)
2023-11-6 23:00 上传
点击文件名下载附件
下载积分: 黑币 -5
作者:
IAIAI
时间:
2023-11-8 17:05
你好,请问是采了四路的电压值吗
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1