第十二届“蓝桥杯”单片机省赛(2)——程序设计题
个人编写,代码仅供参考
如有不足,多多指教
1.题目
2.代码
main.c程序
#include "reg52.h"
#include "iic.h"
//=============================参数定义
uchar code smg[] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xbf,0XFF,0xc1,0x8e,0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10,0x8c,0xc8,0xc6,0x88};
// 0 1 2 3 4 5 6 7 8 9 - mie U F 0. 1. 2. 3. 4. 5. 6. 7. 8. 9. p n C A
sfr AUXR = 0X8E;
sbit s4 = P3^3;
sbit s5 = P3^2;
sbit s6 = P3^1;
sbit s7 = P3^0;
uchar xianshi = 0;//0 频率显示 1 周期显示 2 电压界面
uchar channel = 3;//1 通道一(光敏电阻) 3 通道二(电位器)
float vol_3 = 0.00;//通道三采集的电压
float vol_1 = 0.00;//通道一采集的电压
float vol_3_temp = 0.00;//缓存通道三采集的电压
uint freq = 0;//频率
uint freq_temp = 0;//缓存频率
uchar count_dinshi = 0;//定时
uint count_f = 0;//计数
uint period = 0;
#define period 1000000/freq
uchar s7_press = 0;//s7按下为1 短按为3 长按为2
uchar key_count = 0;//用于s7按下时长计时
uchar led_flag = 1;//led开1 led关0
//=============================函数声明
void select(uchar channel);
void cls_relay_buz_led_smg();
void key_scan();
void smg_delay(uint time);
void smg_dis(uchar pos,uchar val);
void smg_dis_all(uchar val);
void smg_show();
void led_show();
void Init_Timer();
//=============================主函数
void main()
{
cls_relay_buz_led_smg();
Init_Timer();
while(freq == 0);//防止频率还没测量好(数码管没显示),led已经显示一部分
while(1)
{
if(channel == 1)
{
vol_1 = (float)read_pcf_ain1()*5/255;
}
else if(channel == 3)
{
vol_3 = (float)read_pcf_ain3()*5/255;
} //放一个函数同时采集,好像有点冲突问题,故想办法分开采集
key_scan();
smg_show();
led_show();
}
}
//=============================初始化函数
void select(uchar channel)
{
switch(channel)
{
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 cls_relay_buz_led_smg()
{
select(4);
P0 = 0XFF;
select(5);
P0 &= 0xaf;
select(0);
P0 = 0XFF;
select(6);
P0 = 0XFF;
select(7);
P0 = 0xff;
select(0);
}
//=============================按键扫描函数
void key_scan()
{
if(s4 == 0)
{
smg_show();
if(s4 == 0)
{
while(s4 == 0)
{
smg_show();
}
switch(xianshi)
{
case 0 : xianshi = 1;break;
case 1 : channel = 1;xianshi = 2;break;
case 2 : xianshi = 0;break;
}
}
}
if(s5 == 0)
{
smg_show();
if(s5 == 0)
{
while(s5 == 0)
{
smg_show();
}
if(xianshi == 2)
{
switch(channel)
{
case 1 : channel = 3;break;
case 3 : channel = 1;break;
}
}
}
}
if(s6 == 0)
{
smg_show();
if(s6 == 0)
{
while(s6 == 0)
{
smg_show();
}
vol_3 = (float)read_pcf_ain3()*5/255;
vol_3_temp = vol_3;
}
}
if(s7 == 0)
{
smg_show();
if(s7 == 0)
{
while(s7 == 0)
{
smg_show();
}
switch(s7_press)
{
case 2 : if(led_flag == 0){led_flag = 1;}else{led_flag = 0;}s7_press = 0; key_count = 0;break;
case 3 : freq_temp = freq; s7_press = 0; key_count = 0;break;
}
}
}
}
//===================================数码管函数
void smg_delay(uint time)
{
while(time--);
}
void smg_dis(uchar pos,uchar val)
{
select(7);
P0 = 0XFF;
select(6);
P0 = 0x01 << pos;
select(7);
P0 = smg[val];
select(0);
smg_delay(500);
}
void smg_dis_all(uchar val)
{
select(7);
P0 = 0XFF;
select(6);
P0 = 0xff;
select(7);
P0 = smg[val];
select(0);
smg_delay(500);
}
void smg_show()
{
if(xianshi == 0)
{
if(freq >= 1000000)
{
smg_dis(0,13);
smg_dis(1,freq/1000000);
smg_dis(2,freq/100000%10);
smg_dis(3,freq/10000%10);
smg_dis(4,freq/1000%10);
smg_dis(5,freq/100%10);
smg_dis(6,freq/10%10);
smg_dis(7,freq%10);
smg_dis_all(11);
}
else if(freq >= 100000)
{
smg_dis(0,13);
smg_dis(1,11);
smg_dis(2,freq/100000);
smg_dis(3,freq/10000%10);
smg_dis(4,freq/1000%10);
smg_dis(5,freq/100%10);
smg_dis(6,freq/10%10);
smg_dis(7,freq%10);
smg_dis_all(11);
}
else if(freq >= 10000)
{
smg_dis(0,13);
smg_dis(1,11);
smg_dis(2,11);
smg_dis(3,freq/10000);
smg_dis(4,freq/1000%10);
smg_dis(5,freq/100%10);
smg_dis(6,freq/10%10);
smg_dis(7,freq%10);
smg_dis_all(11);
}
else if(freq >= 1000)
{
smg_dis(0,13);
smg_dis(1,11);
smg_dis(2,11);
smg_dis(3,11);
smg_dis(4,freq/1000);
smg_dis(5,freq/100%10);
smg_dis(6,freq/10%10);
smg_dis(7,freq%10);
smg_dis_all(11);
}
else if(freq >= 100)
{
smg_dis(0,13);
smg_dis(1,11);
smg_dis(2,11);
smg_dis(3,11);
smg_dis(4,11);
smg_dis(5,freq/100);
smg_dis(6,freq/10%10);
smg_dis(7,freq%10);
smg_dis_all(11);
}
else if(freq >= 10)
{
smg_dis(0,13);
smg_dis(1,11);
smg_dis(2,11);
smg_dis(3,11);
smg_dis(4,11);
smg_dis(5,11);
smg_dis(6,freq/10);
smg_dis(7,freq%10);
smg_dis_all(11);
}
else if(freq >= 1)
{
smg_dis(0,13);
smg_dis(1,11);
smg_dis(2,11);
smg_dis(3,11);
smg_dis(4,11);
smg_dis(5,11);
smg_dis(6,11);
smg_dis(7,freq);
smg_dis_all(11);
}
}
else if(xianshi == 1)
{
if(period >= 1000000)
{
smg_dis(0,25);
smg_dis(1,period/1000000);
smg_dis(2,period/100000%10);
smg_dis(3,period/10000%10);
smg_dis(4,period/1000%10);
smg_dis(5,period/100%10);
smg_dis(6,period/10%10);
smg_dis(7,period%10);
smg_dis_all(11);
}
else if(period >= 100000)
{
smg_dis(0,25);
smg_dis(1,11);
smg_dis(2,period/100000);
smg_dis(3,period/10000%10);
smg_dis(4,period/1000%10);
smg_dis(5,period/100%10);
smg_dis(6,period/10%10);
smg_dis(7,period%10);
smg_dis_all(11);
}
else if(period >= 10000)
{
smg_dis(0,25);
smg_dis(1,11);
smg_dis(2,11);
smg_dis(3,period/10000);
smg_dis(4,period/1000%10);
smg_dis(5,period/100%10);
smg_dis(6,period/10%10);
smg_dis(7,period%10);
smg_dis_all(11);
}
else if(period >= 1000)
{
smg_dis(0,25);
smg_dis(1,11);
smg_dis(2,11);
smg_dis(3,11);
smg_dis(4,period/1000);
smg_dis(5,period/100%10);
smg_dis(6,period/10%10);
smg_dis(7,period%10);
smg_dis_all(11);
}
else if(period >= 100)
{
smg_dis(0,25);
smg_dis(1,11);
smg_dis(2,11);
smg_dis(3,11);
smg_dis(4,11);
smg_dis(5,period/100);
smg_dis(6,period/10%10);
smg_dis(7,period%10);
smg_dis_all(11);
}
else if(period >= 10)
{
smg_dis(0,25);
smg_dis(1,11);
smg_dis(2,11);
smg_dis(3,11);
smg_dis(4,11);
smg_dis(5,11);
smg_dis(6,period/10);
smg_dis(7,period%10);
smg_dis_all(11);
}
else if(period >= 1)
{
smg_dis(0,25);
smg_dis(1,11);
smg_dis(2,11);
smg_dis(3,11);
smg_dis(4,11);
smg_dis(5,11);
smg_dis(6,11);
smg_dis(7,period);
smg_dis_all(11);
}
}
else if(xianshi == 2)
{
if(channel == 1)
{
// vol_1 = (float)read_pcf_ain1()*5/255;
smg_dis(0,12);
smg_dis(1,10);
smg_dis(2,channel);
smg_dis(3,11);
smg_dis(4,11);
smg_dis(5,(uint)(vol_1*100)/100+14);
smg_dis(6,(uint)(vol_1*100)/10%10);
smg_dis(7,(uint)(vol_1*100)%10);
smg_dis_all(11);
}
else if(channel == 3)
{
// vol_3 = (float)read_pcf_ain3()*5/255;
smg_dis(0,12);
smg_dis(1,10);
smg_dis(2,channel);
smg_dis(3,11);
smg_dis(4,11);
smg_dis(5,(uint)(vol_3*100)/100+14);
smg_dis(6,(uint)(vol_3*100)/10%10);
smg_dis(7,(uint)(vol_3*100)%10);
smg_dis_all(11);
}
}
}
//=========================计数器0,定时器1 获取频率为 freq
void Init_Timer()
{
TH0 = 0xff;
TL0 = 0xff;
TH1 = 0X3C;
TL1 = 0XB0;
TMOD = 0x04; //定时器1用十六位自动重载,定时,50ms;定时器0用十六位自动重载,计数,1us;
ET0 = 1;
ET1 = 1;
EA = 1;
TR0 = 1;
TR1 = 1;
}
void ser_counter() interrupt 1
{
count_f++;
}
void ser_timer() interrupt 3
{
if(s7 == 0)
{
key_count++;
if(key_count >= 20)
{
s7_press = 2;
}
else
{
s7_press = 3;
}
}
count_dinshi++;
if(count_dinshi == 20)
{
freq = count_f;
count_dinshi = 0;
count_f = 0;
}
}
//=========================================LED函数
void led_show()
{
if(led_flag == 1)
{
if(vol_3 > vol_3_temp)
{
select(4);
P0 = P0 & 0XFE;
select(0);
}
else
{
select(4);
P0 = P0 | 0x01;
select(0);
}
if(freq > freq_temp)
{
select(4);
P0 = P0 & 0xfd;
select(0);
}
else
{
select(4);
P0 = P0 | 0x02;
select(0);
}
if(xianshi == 0)
{
select(4);
P0 = (P0 & 0xfb) | 0x18;
select(0);
}
else if(xianshi == 1)
{
select(4);
P0 = (P0 & 0xf7) | 0x14;
select(0);
}
else if(xianshi == 2)
{
select(4);
P0 = (P0 & 0xef) | 0x0c;
select(0);
}
}
else if(led_flag == 0)
{
select(4);
P0 = 0xff;
select(0);
}
}
iic.c程序
#include "iic.h"
#define DELAY_TIME 5
//I2C总线内部延时函数
void IIC_Delay(unsigned char i)
{
do{_nop_();}
while(i--);
}
//I2C总线启动信号
void IIC_Start(void)
{
SDA = 1;
SCL = 1;
IIC_Delay(DELAY_TIME);
SDA = 0;
IIC_Delay(DELAY_TIME);
SCL = 0;
}
//I2C总线停止信号
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;
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;
}
//======================================pcf读取函数
uchar read_pcf_ain3()//resistor
{
uchar ain3;
IIC_Start();
IIC_SendByte(0x90);
IIC_WaitAck();
IIC_SendByte(0x03);
IIC_WaitAck();
IIC_Stop();
IIC_Start();
IIC_SendByte(0x91);
IIC_WaitAck();
ain3 = IIC_RecByte();
IIC_SendAck(1);
IIC_Stop();
return ain3;
}
uchar read_pcf_ain1()//light resisitor
{
uchar ain1;
IIC_Start();
IIC_SendByte(0x90);
IIC_WaitAck();
IIC_SendByte(0x01);
IIC_WaitAck();
IIC_Stop();
IIC_Start();
IIC_SendByte(0x91);
IIC_WaitAck();
ain1 = IIC_RecByte();
IIC_SendAck(1);
IIC_Stop();
return ain1;
}
iic.h程序
#ifndef _IIC_H
#define _IIC_H
#include "reg52.h"
#include "intrins.h"
sbit SDA = P2^1;
sbit SCL = P2^0;
void IIC_Start(void);
void IIC_Stop(void);
bit IIC_WaitAck(void);
void IIC_SendAck(bit ackbit);
void IIC_SendByte(unsigned char byt);
unsigned char IIC_RecByte(void);
uchar read_pcf_ain3();//resistor
uchar read_pcf_ain1();//light resisitor
#endif