题目和完整代码贴在下面了,本文采用互动的方法由大家一起来逐步完善。
具体方法是大家看代码觉得有啰嗦,错误的地方或者有看不懂得地方就在评论区留言,我看到后会在第一时间做详细的解释,修改文章,增加注释。以此来使大家能完全掌握这个题目。
![](https://i-blog.csdnimg.cn/blog_migrate/8d3882eb7537e986f9190dcd3defc1c1.png)
![](https://i-blog.csdnimg.cn/blog_migrate/3c3aede3e12814f0c498ea3ea30ef8ea.png)
![](https://i-blog.csdnimg.cn/blog_migrate/0172af784619e815bfd1f1cf23440f5b.png)
![](https://i-blog.csdnimg.cn/blog_migrate/5c25b4913af7f97d9a7533beab445bf3.png)
![](https://i-blog.csdnimg.cn/blog_migrate/64f3c12833e2ff49d491926e1772c7b2.png)
![](https://i-blog.csdnimg.cn/blog_migrate/5255341fe5fa5f8df9de2ec6edbe3df3.png)
![](https://i-blog.csdnimg.cn/blog_migrate/71a6216d996978fb6423d35063102598.png)
main.c
#include"reg52.h"
#include"smg.h"
#include"iic.h"
sbit S7 = P3^0;
sbit S6 = P3^1;
sbit S5 = P3^2;
sbit S4 = P3^3;
sbit L1 = P0^0;
sbit L2 = P0^1;
sbit L3 = P0^2;
sbit L4 = P0^3;
sbit L7 = P0^6;
sbit L8 = P0^7;
void SMG_XS();
unsigned int channel_three = 0;
unsigned int count_t=0;
unsigned int count_f=0;
unsigned int dat_f=0;
unsigned char state_uf,state_da,i,j,stat_led,stat_smg,stat_led,state_S6,state_S7;
//===============延时=========================
void Delay10ms() //@11.0592MHz
{
unsigned char i, j, k;
for(k = 0;k <= 9;k++)//通过for 实际延时100ms
{
i = 108;
j = 145;
do
{
while (--j);
} while (--i);
}
}
//========================================
//频率测量模块==========================
void Init_Timer()
{
TH1 = (65535 - 1000)/256;//1ms
TL1 = (65535 - 1000)%256;
TH0 = 0xff;
TL0 = 0xff;
TMOD = 0X16;
EA = 1;
ET1 = 1;
ET0 = 1;
TR0 = 1;
TR1 = 1;
}
void Service_T0() interrupt 1
{
count_f++;
}
void Service_T1() interrupt 3
{
TH1 = (65535 - 1000)/256;
TL1 = (65535 - 1000)%256;
SMG_XS();
count_t++;
if(count_t%100 == 0)//每100ms对LED状态更新一次
{
if(state_S6 == 0)//S6具有禁用LED功能,设置一个由按键S6控制的状态参数在此判断
{
InitHC138(4);
P0 = stat_led;
InitHC138(0);
}
}
if(count_t==1000)
{
dat_f = count_f;
count_t=0;
count_f=0;
}
}
void SMG_XS()
{
if(state_S7 == 0)//S7具有禁用数码管功能,设置一个由按键S7控制的状态参数在此判断
{
if(state_uf == 0)//显示电压的部分
{
i++;
if(i == 8)
{
i = 0;
}
switch(i)
{
case 0 :
DisPlaySMG_Bit(0,0xc1);//1100 0001
break;
case 1:
DisPlaySMG_Bit(1,0xff);
break;
case 2:
DisPlaySMG_Bit(2,0xff);
break;
case 3:
DisPlaySMG_Bit(3,0xff);
break;
case 4:
DisPlaySMG_Bit(4,0xff);
break;
case 5:
DisPlaySMG_Bit(5,SMGDot_CA[channel_three*5/256]);//括号不要乱加,如果是(5/256)结果是0
break;
case 6:
DisPlaySMG_Bit(6,SMGNoDot_CA[channel_three*50/256%10]);//结果是 0.00 的形式,我们要小数点后一位,要在 前面 先乘以10,得到一个二位数去取余
break;
case 7:
DisPlaySMG_Bit(7,SMGNoDot_CA[channel_three*500/256%10]);//同样,乘以100要放在前面,如果先除256取整,得到的是0,再乘100也没有意义了
break;
}
}
if(state_uf == 1)//显示频率的部分
{
j++;
if(j == 8)
{
j = 0;
}
switch(j)
{
case 0:
DisPlaySMG_Bit(0,SMGNoDot_CA[15]);
break;
case 1:
DisPlaySMG_Bit(1,0xff);
break;
case 2:
DisPlaySMG_Bit(2,0xff);
break;
case 3:
if(dat_f > 9999)
{
DisPlaySMG_Bit(3,SMGNoDot_CA[dat_f/10000]);
}
break;
case 4:
if(dat_f > 999)
{
DisPlaySMG_Bit(4,SMGNoDot_CA[(dat_f/1000)%10]);
}
break;
case 5:
if(dat_f > 99)
{
DisPlaySMG_Bit(5,SMGNoDot_CA[(dat_f/100)%10]);
}
break;
case 6:
if(dat_f > 9)
{
DisPlaySMG_Bit(6,SMGNoDot_CA[(dat_f/10)%10]);
}
break;
case 7:
DisPlaySMG_Bit(7,SMGNoDot_CA[(dat_f/1)%10]);
break;
}
}
}
}
//===============按键============================
void delayk(unsigned char time)
{
while(time--);
}
void ScanKeys()
{
if(S4 == 0)//控制测量电压还是频率
{
delayk(100);
if(S4 == 0)
{
while(S4 == 0);
stat_led = (stat_led | 0x03) & (~stat_led | 0xfc);//S4按下,测量状态切换,这里对L1 L2 两个灯取反
if(state_uf == 1)
{
state_uf = 0;//转为测电压
}
else//这里不能用连用两个if 因为经过上面的if后,state的值被改变了
{
state_uf = 1;
}
}
}
if(S5 == 0)//状态0 输出2V 状态1 输出跟随ad
{
delayk(100);
if(S5 == 0)
{
while(S5 == 0);
stat_led = (stat_led | 0x10) & (~stat_led | 0xef);
if(state_da == 1)
{
state_da = 0;
write_8591(102);
}
else
{
state_da = 1;
write_8591(channel_three);
}
}
}
if(S6 == 0)
{
delayk(100);
if(S6 == 0)
{
while(S6 == 0);
if(state_S6 == 0)
{
state_S6 = 1;//L6状态参数,为1时将不能对LED进行操作(除此处外唯一能对LED操作的在中断服务函数中,在服务函数中会进行判断)
InitHC138(4);
P0 = 0xff;
InitHC138(0);
}
else
{
state_S6 = 0;
}
}
}
if(S7 == 0)
{
delayk(100);
if(S7 == 0)
{
while(S7 == 0);
if(state_S7 == 0)
{
state_S7 = 1;
All_SMG();
}
else
{
state_S7 = 0;
}
}
}
}
//==========================
//===============================================
void main()
{
Init_Timer();
InitHC138(4);
stat_led = 0xfe;
P0 = stat_led;//1111 1110
InitHC138(0);
while(1)
{
ScanKeys();
channel_three = red_8591(3);
Delay10ms();
if(channel_three < 77 || (channel_three < 179 && channel_three > 127))
{
stat_led = (stat_led | 0x04) & 0xff;//把L3置1
}
if((channel_three > 77 && channel_three < 127)|| channel_three > 179)//||逻辑运算符
{
stat_led = (stat_led | 0x04) & 0xfb;//把L3置0
}
if(dat_f < 1000 || (dat_f >= 5000 && dat_f < 10000))
{
stat_led = (stat_led | 0x08) & 0xff;
}
if(dat_f >= 10000 || (dat_f >= 1000 && dat_f < 5000))
{
stat_led = (stat_led | 0x08) & 0xf7;
}
}
}
smg.c
#include"reg52.h"
void InitHC138(unsigned char n)
{
switch(n)
{
case 4:
P2 = (P2&0X1F) | 0X80;
break;
case 5://·äÃùÆ÷ ¼ÌµçÆ÷
P2 = (P2&0X1F) | 0Xa0;
break;
case 6:
P2 = (P2&0X1F) | 0Xc0;
break;
case 7:
P2 = (P2&0X1F) | 0Xe0;
break;
case 0:
P2 = (P2&0X1F) | 0X00;
break;
}
}
//================ÑÓʱ================
void DelaySMG(unsigned char t)
{
while(t--);
}
void DisPlaySMG_Bit(unsigned char pos,unsigned char dat)
{
P0 = 0xff;
InitHC138(6);
P0 = 0X01 << pos;
InitHC138(7);
P0 = dat;
}
//==========================
void All_SMG()//ÏûÓ°
{
InitHC138(6);
P0 = 0xff;
InitHC138(7);
P0 = 0xff;
}
iic.c
//pcf8591µÄ¶Áд
#include "reg52.h"
#include "intrins.h"
#define DELAY_TIME 5
#define SlaveAddrW 0xA0
#define SlaveAddrR 0xA1
sbit SDA = P2^1;
sbit SCL = P2^0;
void IIC_Delay(unsigned char i)
{
do{_nop_();}
while(i--);
}
//×ÜÏßÆô¶¯Ìõ¼þ
void IIC_Start(void)
{
SDA = 1;
SCL = 1;
IIC_Delay(DELAY_TIME);
SDA = 0;
IIC_Delay(DELAY_TIME);
SCL = 0;
}
//×ÜÏßÍ£Ö¹Ìõ¼þ
void IIC_Stop(void)
{
SDA = 0;
SCL = 1;
IIC_Delay(DELAY_TIME);
SDA = 1;
IIC_Delay(DELAY_TIME);
}
//·¢ËÍÓ¦´ð
void IIC_SendAck(bit ackbit)
{
SCL = 0;
SDA = ackbit; // 0£ºÓ¦´ð£¬1£º·ÇÓ¦´ð
IIC_Delay(DELAY_TIME);
SCL = 1;
IIC_Delay(DELAY_TIME);
SCL = 0;
SDA = 1;
IIC_Delay(DELAY_TIME);
}
//µÈ´ýÓ¦´ð
bit IIC_WaitAck(void)
{
bit ackbit;
SCL = 1;
IIC_Delay(DELAY_TIME);
ackbit = SDA;
SCL = 0;
IIC_Delay(DELAY_TIME);
return ackbit;
}
//ͨ¹ýI2C×ÜÏß·¢ËÍÊý¾Ý
void IIC_SendByte(unsigned char byt)
{
unsigned char i;
for(i=0; i<8; i++)
{
SCL = 0;
IIC_Delay(DELAY_TIME);
if(byt & 0x80) SDA = 1;
else SDA = 0;
IIC_Delay(DELAY_TIME);
SCL = 1;
byt <<= 1;
IIC_Delay(DELAY_TIME);
}
SCL = 0;
}
//´ÓI2C×ÜÏßÉϽÓÊÕÊý¾Ý
unsigned char IIC_RecByte(void)
{
unsigned char i, da;
for(i=0; i<8; i++)
{
SCL = 1;
IIC_Delay(DELAY_TIME);
da <<= 1;
if(SDA) da |= 1;
SCL = 0;
IIC_Delay(DELAY_TIME);
}
return da;
}
void write_8591(unsigned char dac)
{
IIC_Start();
IIC_SendByte(0x90);//дµØÖ·
IIC_WaitAck();
IIC_SendByte(0x40);//д¿ØÖÆ×Ö½Ú Ä£ÄâÊä³öʹÄÜ£¬daģʽ
IIC_WaitAck();
IIC_SendByte(dac);//дÊý¾Ý
IIC_WaitAck();
IIC_Stop();
}
unsigned int red_8591(unsigned int channle_n)
{
IIC_Start();
IIC_SendByte(0x90);//дµØÖ·
IIC_WaitAck();
IIC_SendByte(channle_n);//д¿ØÖÆ×Ö½Ú adģʽ
IIC_WaitAck();
IIC_Start();
IIC_SendByte(0x91);//¶ÁµØÖ·
IIC_WaitAck();
channle_n = IIC_RecByte();
IIC_SendAck(0);
channle_n = IIC_RecByte();//ÿ´Î¶Áµ½µÄ¶¼ÊÇÉÏÒ»´Îת»¯µÃµ½µÄ½á¹û,ËùÒÔ¶ÁÁ½´Î
IIC_Stop();
return channle_n;
}