第十届“蓝桥杯”单片机省赛——程序设计题
个人编写,代码仅供参考
如有不足,多多指教
1.题目
2.代码
main.c程序
#include "reg52.h"
#include "iic.h"
#include "intrins.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};
// 0 1 2 3 4 5 6 7 8 9 - mie U F 0. 1. 2. 3. 4. 5. 6. 7. 8. 9.
//======================延时函数
void delay_smg(uint time)
{
while(time--);
}
//====================参数定义
sfr AUXR = 0X8E;
sbit s4 = P3^3;
sbit s5 = P3^2;
sbit s6 = P3^1;
sbit s7 = P3^0;
sbit l1 = P0^0;
sbit l2 = P0^1;
sbit l3 = P0^2;
sbit l4 = P0^3;
sbit l5 = P0^4;
uint count_f;//计数器计数用
uchar count_dinshi;//定时器用
uint dat_f;//频率
uchar value_resis_temp;//从pcf读取的电位器的电压的0~255值
#define value_resis 5*((float)value_resis_temp/255)//电位器的电压(实际)
uchar value_output_temp;//让pcf输出的电压0~255值
#define value_output (float)(5*(value_output_temp/255))//让pcf输出的电压(实际)
//当shuchu_flag = 1 value_output_temp = 102 (2v)
//当shuchu_flag = 0 value_output_temp = value_resis_temp
uchar celiang_flag = 1; // 1 电压测量 0 频率测量
uchar shuchu_flag = 1; // 1 2v固定输出 0 跟随测量输出
uchar led_flag = 1; // 1 led启用 0 led关闭
uchar smg_flag = 1; // 1 smg启用 0 smg关闭
//========================函数定义
void key_scan();
void init();
void smg_dis(uchar pos,uchar val);
void smg_show();
void Init_Timer();
void get_resis();
void smg_dis_all(uchar val);
void pcf_dac_output();
void led_show();
//=========================主函数
void main()
{
init();
Init_Timer();
while(1)
{
key_scan();
get_resis();
pcf_dac_output();
led_show();
smg_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 init()
{
select(5);
P0 &= 0XAF;
select(4);
P0 = 0XFF;
select(6);
P0 = 0XFF;
select(7);
P0 = smg[11];
select(0);
P0 = 0XFF;
}
//========================按键扫描
void key_scan()
{
if(s4 == 0)
{
smg_show();
if(s4 == 0)
{
while(s4 == 0)
{
smg_show();
}
switch(celiang_flag)
{
case 1 : celiang_flag = 0;break;
case 0 : celiang_flag = 1;break;
}
}
}
if(s5 == 0)
{
smg_show();
if(s5 == 0)
{
while(s5 == 0)
{
smg_show();
}
switch(shuchu_flag)
{
case 1 : shuchu_flag = 0;break;
case 0 : shuchu_flag = 1;break;
}
}
}
if(s6 == 0)
{
smg_show();
if(s6 == 0)
{
while(s6 == 0)
{
smg_show();
}
switch(led_flag)
{
case 1 : led_flag = 0;break;
case 0 : led_flag = 1;break;
}
}
}
if(s7 == 0)
{
smg_show();
if(s7 == 0)
{
while(s7 == 0)
{
smg_show();
}
switch(smg_flag)
{
case 1 : smg_flag = 0;break;
case 0 : smg_flag = 1;break;
}
}
}
}
//==========================数码管函数
void smg_dis(uchar pos,uchar val)
{
select(7);
P0 = 0XFF;
select(6);
P0 = 0X01 << pos;
select(7);
P0 = smg[val];
select(0);
delay_smg(500);
}
void smg_dis_all(uchar val)
{
select(6);
P0 = 0XFF;
select(7);
P0 = smg[val];
select(0);
}
//=========================计数器0,定时器1 获取频率为 dat_f
void Init_Timer()
{
TH0 = 0xff;
TL0 = 0xff;
TH1 = (65536 - 50000) / 256;
TL1 = (65536 - 50000) % 256;
TMOD = 0x16; //定时器1用方式1,定时;定时器0用方式2,计数
ET0 = 1;
ET1 = 1;
EA = 1;
TR0 = 1;
TR1 = 1;
}
void ser_counter() interrupt 1
{
count_f++;
}
void ser_timer() interrupt 3
{
TH1 = (65536 - 50000) / 256;
TL1 = (65536 - 50000) % 256;
count_dinshi++;
if(count_dinshi == 20)
{
dat_f = count_f;
count_dinshi = 0;
count_f = 0;
}
}
//=======================获取输出电压
void get_resis()
{
value_resis_temp = pcf_adc();
}
//=======================数码管显示函数
void smg_show()
{
if(smg_flag == 0)
{
smg_dis_all(11);
}
else
{
if(celiang_flag == 1)
{
smg_dis(0,12);
smg_dis(1,11);
smg_dis(2,11);
smg_dis(3,11);
smg_dis(4,11);
smg_dis(5,((int)((value_resis*100))/100)+14);
smg_dis(6,(((int)((value_resis*100))/10))%10);
smg_dis(7,((int)((value_resis*100)))%10);
smg_dis_all(11);
}
else if(celiang_flag == 0)
{
if(dat_f >= 100000)
{
smg_dis(0,13);
smg_dis(1,11);
smg_dis(2,dat_f/100000);
smg_dis(3,(dat_f/10000)%10);
smg_dis(4,(dat_f/1000)%10);
smg_dis(5,(dat_f/100)%10);
smg_dis(6,(dat_f/10)%10);
smg_dis(7,dat_f%10);
smg_dis_all(11);
}
else if(dat_f >= 10000)
{
smg_dis(0,13);
smg_dis(1,11);
smg_dis(2,11);
smg_dis(3,dat_f/10000);
smg_dis(4,(dat_f/1000)%10);
smg_dis(5,(dat_f/100)%10);
smg_dis(6,(dat_f/10)%10);
smg_dis(7,dat_f%10);
smg_dis_all(11);
}
else if(dat_f >= 1000)
{
smg_dis(0,13);
smg_dis(1,11);
smg_dis(2,11);
smg_dis(3,11);
smg_dis(4,dat_f/1000);
smg_dis(5,(dat_f/100)%10);
smg_dis(6,(dat_f/10)%10);
smg_dis(7,dat_f%10);
smg_dis_all(11);
}
else if(dat_f >= 100)
{
smg_dis(0,13);
smg_dis(1,11);
smg_dis(2,11);
smg_dis(3,11);
smg_dis(4,11);
smg_dis(5,dat_f/100);
smg_dis(6,(dat_f/10)%10);
smg_dis(7,dat_f%10);
smg_dis_all(11);
}
else if(dat_f >= 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,dat_f/10);
smg_dis(7,dat_f%10);
smg_dis_all(11);
}
else if(dat_f >= 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,dat_f);
smg_dis_all(11);
}
}
//
}
}
//========================pcf输出函数
void pcf_dac_output()
{
switch(shuchu_flag)
{
case 1 : value_output_temp = 102 + 5;break;//输出误差5
case 0 : value_output_temp = value_resis_temp + 5;break;//输出误差5
}
pcf_dac(value_output_temp);
}
//========================led功能显示
void led_show()
{
if(led_flag == 0)//led没有启用
{
select(4);
P0 = 0XFF;
select(0);
P0 = 0XFF;
}
else if(led_flag == 1)//led启用
{
if(celiang_flag == 1)
{
select(4);
P0 = (P0 & 0XFE) | 0XE2;
select(0);
}
else if(celiang_flag == 0)
{
select(4);
P0 = (P0 & 0XFD) | 0XE1;
select(0);
}
if(value_resis < 1.5)
{
select(4);
P0 |= 0XE4;
select(0);
}
else if(value_resis < 2.5 && value_resis >= 1.5)
{
select(4);
P0 = (P0 & 0XFB) | 0XE0;
select(0);
}
else if(value_resis < 3.5 && value_resis >= 2.5)
{
select(4);
P0 |= 0XE4;
select(0);
}
else if(value_resis >= 3.5)
{
select(4);
P0 = (P0 & 0XFB) | 0XE0;
select(0);
}
if(dat_f < 1000)
{
select(4);
P0 |= 0XE8;
select(0);
}
else if(dat_f < 5000 && dat_f >= 1000)
{
select(4);
P0 = (P0 & 0XF7) | 0XE0;
select(0);
}
else if(dat_f < 10000 && dat_f >= 5000)
{
select(4);
P0 |= 0XE8;
select(0);
}
else if(dat_f >= 10000)
{
select(4);
P0 = (P0 & 0XF7) | 0XE0;
select(0);
}
if(shuchu_flag == 1)//如果固定输出2v,led5 灭
{
select(4);
P0 |= 0XF0;
select(0);
}
else if(shuchu_flag == 0)//如果固定输出跟随,led5 亮
{
select(4);
P0 = (P0 & 0XEF) | 0XE0;
select(0);
}
}
}
//======================END
iic.c程序
/*
程序说明: IIC总线驱动程序
软件环境: Keil uVision 4.10
硬件环境: CT107单片机综合实训平台 8051,12MHz
日 期: 2011-8-9
*/
#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;
}
//===========================================
uchar pcf_adc()
{
uchar temp;
IIC_Start();
IIC_SendByte(0X90);
IIC_WaitAck();
IIC_SendByte(0X03);
IIC_WaitAck();
IIC_Stop();
IIC_Start();
IIC_SendByte(0X91);
IIC_WaitAck();
temp = IIC_RecByte();
IIC_SendAck(1);
IIC_Stop();
return temp;
}
void pcf_dac(uchar dat)//dat (0,255)
{
IIC_Start();
IIC_SendByte(0X90);
IIC_WaitAck();
IIC_SendByte(0X43);
IIC_WaitAck();
IIC_SendByte(dat);
IIC_WaitAck();
IIC_Stop();
}
iic.h程序
#ifndef _IIC_H
#define _IIC_H
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);
void pcf_dac(uchar dat);
uchar pcf_adc();
#endif
=================================//欢迎指正//===============================