要求
在单片机综合训练平台上,实现以下功能:
1.IIC总线底层驱动引入文件
2.光敏电阻rd1接到PCF8591的AIN1通道,可调电阻rb2接到PCF8591的AIN3通道
3.系统上电后,循环采样AIN1和AIN3通道的电压,并将A/D转换结果读出,换算成对应的实际电压值,保留2位小数,单位为V
4.数码管显示采样的实时电压
代码
题目
系统上电后,循环采样AIN1和AIN3通道的电压,并将A/D转换结果读出,换算成对应的实际电压值,保留2位小数,单位为V
一共3个步骤:采样数据 + 换算电压 + 显示电压
所以需要定义3个变量:
//-----------------------------------------------
unsigned char adc1_value = 0; //AIN1的采样数据
float adc1_volt = 0; //AIN1的换算电压
unsigned int smg1_volt = 0; //AIN1的显示电压
unsigned char adc3_value = 0; //AIN3的采样数据
float adc3_volt = 0; //AIN3的换算电压
unsigned int smg3_volt = 0; //AIN3的显示电压
它们的相关函数为:
//=============采样光敏电阻和可调电阻的电压=============
void Read_AIN1_AIN3()
{
adc1_value = Read_PCF8591_ADC(1);
adc1_volt = adc1_value * (5.0 / 255);
smg1_volt = adc1_volt * 100;
adc3_value = Read_PCF8591_ADC(3);
adc3_volt = adc3_value * (5.0 / 255);
smg3_volt = adc3_volt * 100;
}
最重要的是电压采样处理函数!!!
涉及A/D转换!!!
ain指的是在哪个通道
//===============PCF8591电压采样处理函数===============
unsigned char Read_PCF8591_ADC(unsigned char ain)
{
unsigned char tmp;
IIC_Start();
IIC_SendByte(0x90); //PCF8591的写设备地址
IIC_WaitAck();
if(ain == 1)
{
IIC_SendByte(0x01); //通道1,光敏电阻电压
}
else if(ain == 3)
{
IIC_SendByte(0x03); //通道3,可调电阻电压
}
IIC_WaitAck();
IIC_Stop();
DisplaySMG_ADC(); //等待电压转换完成
IIC_Start();
IIC_SendByte(0x91); //PCF8591的读设备地址
IIC_WaitAck();
tmp = IIC_RecByte(); //读出AD采样数据
IIC_SendAck(1); //产生非应答信号
IIC_Stop();
return tmp;
}
完整代码
====================================================*/
#include "reg52.h"
#include "iic.h"
//定义动态显示中单个数码管点亮时长
#define TSMG 500
//-------共阳数码管的段码编码表(无小数点)--------
//0 1 2 3 4 5 6 7 8 9 A B C D E F - .
unsigned char code SMG_NoDot[18]={0xc0,0xf9,
0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,
0x88,0x80,0xc6,0xc0,0x86,0x8e,0xbf,0x7f};
//-------共阳数码管的段码编码表(带小数点)--------
//0. 1. 2. 3. 4. 5. 6. 7. 8. 9.
unsigned char code SMG_Dot[10]={0x40,0x79,
0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10};
//-----------------------------------------------
unsigned char adc1_value = 0; //AIN1的采样数据
float adc1_volt = 0; //AIN1的换算电压
unsigned int smg1_volt = 0; //AIN1的显示电压
unsigned char adc3_value = 0; //AIN3的采样数据
float adc3_volt = 0; //AIN3的换算电压
unsigned int smg3_volt = 0; //AIN3的显示电压
//==============数码管动态显示专用延时函数=============
void DelaySMG(unsigned int t)
{
while(t--);
}
//==================设置选通的锁存器===================
void Set_HC573(unsigned char channel, unsigned char dat)
{
P0 = dat; //待设置数据
switch(channel) //选通锁存器
{
case 4:
P2 = (P2 & 0x1f) | 0x80; //Y4输出0,LED控制
break;
case 5:
P2 = (P2 & 0x1f) | 0xa0; //Y5输出0,蜂鸣器和继电器控制
break;
case 6:
P2 = (P2 & 0x1f) | 0xc0; //Y6输出0,数码管位选
break;
case 7:
P2 = (P2 & 0x1f) | 0xe0; //Y7输出0,数码管段码
break;
case 0:
P2 = (P2 & 0x1f) | 0x00; //所有锁存器不选择
break;
}
P2 = (P2 & 0x1f) | 0x00; //设置完成,关闭全部锁存器
}
//=================单个数码管动态显示=================
void DisplaySMG_Bit(unsigned char pos, unsigned char value)
{
Set_HC573(6, 0x01 << pos); //数码管的段位
Set_HC573(7, value); //数码管显示内容
DelaySMG(TSMG); //数码管点亮时长
Set_HC573(6, 0x01 << pos);
Set_HC573(7, 0xff); //消隐
}
//=================全部数码管静态显示=================
void DisplaySMG_All(unsigned char value)
{
Set_HC573(6, 0xff); //使能所有数码管
Set_HC573(7, value); //数码管显示内容
}
//===================电压值显示函数===================
void DisplaySMG_ADC()
{
//数码管右起第0位
DisplaySMG_Bit(7,SMG_NoDot[smg1_volt % 10]);
//数码管右起第1位
DisplaySMG_Bit(6,SMG_NoDot[(smg1_volt / 10) % 10]);
//数码管右起第2位
DisplaySMG_Bit(5,SMG_Dot[smg1_volt / 100]);
//数码管右起第5位
DisplaySMG_Bit(2,SMG_NoDot[smg3_volt % 10]);
//数码管右起第6位
DisplaySMG_Bit(1,SMG_NoDot[(smg3_volt / 10) % 10]);
//数码管右起第7位
DisplaySMG_Bit(0,SMG_Dot[smg3_volt / 100]);
}
//===============PCF8591电压采样处理函数===============
unsigned char Read_PCF8591_ADC(unsigned char ain)
{
unsigned char tmp;
IIC_Start();
IIC_SendByte(0x90); //PCF8591的写设备地址
IIC_WaitAck();
if(ain == 1)
{
IIC_SendByte(0x01); //通道1,光敏电阻电压
}
else if(ain == 3)
{
IIC_SendByte(0x03); //通道3,可调电阻电压
}
IIC_WaitAck();
IIC_Stop();
DisplaySMG_ADC(); //等待电压转换完成
IIC_Start();
IIC_SendByte(0x91); //PCF8591的读设备地址
IIC_WaitAck();
tmp = IIC_RecByte(); //读出AD采样数据
IIC_SendAck(1); //产生非应答信号
IIC_Stop();
return tmp;
}
//=============采样光敏电阻和可调电阻的电压=============
void Read_AIN1_AIN3()
{
adc1_value = Read_PCF8591_ADC(1);
adc1_volt = adc1_value * (5.0 / 255);
smg1_volt = adc1_volt * 100;
adc3_value = Read_PCF8591_ADC(3);
adc3_volt = adc3_value * (5.0 / 255);
smg3_volt = adc3_volt * 100;
}
//=====================系统初始化=====================
void Init_sys()
{
Set_HC573(0, 0x00); //关闭所有锁存器
Set_HC573(5, 0x00); //关闭蜂鸣器和继电器
Set_HC573(4, 0xff); //关闭全部LED灯
DisplaySMG_All(0xff); //关闭全部数码管
}
//=======================主函数=======================
void main()
{
Init_sys(); //系统初始化
while(1)
{
Read_AIN1_AIN3(); //循环采样电压
DisplaySMG_ADC(); //动态刷新数码管
}
}
//========================END=========================
总结
1.A/D转换需要定义3个变量,需要AD转换函数、采样函数
2.涉及小数,注意数码管的显示函数