赞
踩
今年的蓝桥杯第一场单片机与设计,我个人认为要比去年的简单一些。其中有几个功能在今年的模拟赛中就有考察。话不多说上代码
首先主函数
#include "stdio.h" #include "Timer.h" #include "onewire.h" #include "Init.h"//初始化 #include "Key.h"//key #include "Seg.h"// seg #include "Led.h"//led #include "iic.h" void Key_Proc(void); void Seg_Proc(void); void Led_Proc(void); unsigned long ms_Tick = 0;//定时器与显示用 unsigned int Key_Slow_Down;//按键减速用 unsigned int Seg_Slow_Down;//数码管减速用 unsigned int Led_Slow_Down;//LED灯减速用 unsigned char Key_Value; //按键用 unsigned char Key_Old, Key_Down; unsigned char seg_string[10];//数码管用 unsigned char seg_buf[8]; unsigned char pos; unsigned char ucLed;//Led用 unsigned char ucled1,ucled2; //界面与模式的灯 unsigned int ucSec;//配合ms_Tick变量使用的计数变量 unsigned char Runing_Mode=0;//0是温度界面,1是参数界面,2是DAC界面 unsigned char Dac_Mode=0;//0是模式1,1是模式2 unsigned char Wendu_Canshu,Wendu_Canshu_S=25; float Wendu,Dac_Value; void main(void) { Init_System();//初始化系统关闭LED/继电器/蜂鸣器 Timer1Init();//定时器1初始化 EA = 1;//打开总中断 while(1) { Key_Proc();//调用按键函数 Seg_Proc(); Led_Proc(); } }
初始化程序
void Init_System(void)
{
P0 = 0XFF;
P2 = P2 & 0X1F | 0x80;//关LED
P2 &= 0X1F;
P0 = 0X00;
P2 = P2 & 0X1F | 0xA0;//关闭蜂鸣器和继电器
P2 &= 0X1F;
}
Key_Proc函数
void Key_Proc(void) { if(Key_Slow_Down) return; Key_Slow_Down = 1; Key_Value = Key_Read();//读取按键函数 Key_Down = Key_Value & (Key_Old ^ Key_Value);//下降沿输入 Key_Old = Key_Value;//检测电平变化, switch(Key_Down)// { case 4: Runing_Mode++; if(Runing_Mode==3)//使界面在温度显示,温度设置界面,DAC输出界面轮转 Runing_Mode=0; if(Runing_Mode!=1) Wendu_Canshu=Wendu_Canshu_S;//使设定的温度参数在退出设置界面时才有效 break;//界面切换 case 5: Dac_Mode^=1; //DAC电压输出模式在模式1到2中切换 break;//模式切换 case 8: if(Runing_Mode==1) { if(Wendu_Canshu_S>0)//温度参数最低为0(个人设置) Wendu_Canshu_S--; } break;//温度参数减 case 9: if(Runing_Mode==1) { if(Wendu_Canshu_S<99)//最高为99(避免多一位数多占个数码管) Wendu_Canshu_S++; } break;//温度参数加 } }
Seg_Proc函数
void Seg_Proc(void) { if(Seg_Slow_Down) return; Seg_Slow_Down = 1; Wendu=(rd_temperature()/16.0); if(Runing_Mode==0)//温度界面 { sprintf(seg_string,"C %5.2f",Wendu);//显示温度 } else if(Runing_Mode==1)//温度参数界面 { sprintf(seg_string,"P %2d",(unsigned int)Wendu_Canshu_S); } else if(Runing_Mode==2)//DAC界面 { sprintf(seg_string,"A %4.2f",Dac_Value); } if(Dac_Mode==0)//DAc模式1 { if(Wendu<Wendu_Canshu)//实际温度小于温度参数输出为0 { Dac_Value=0;//两种不同DAc模式下的电压输出 } else Dac_Value=5;//大于则输出为5V } else if(Dac_Mode==1)//DAC 模式2 { if(Wendu<20)//实际温度在20度下输出为1V { Dac_Value=1; } else if(Wendu>40)//实际温度大于40度输出为4V { Dac_Value=4; } else Dac_Value=(Wendu-20)*0.15+1; }//实际温度在20到40间一摄氏度等于0.15V,当然要加上小于20度时的1V Pcf8591_Dac(Dac_Value*51); //按键盘选择的模式DAC输出电压 Seg_Tran(seg_string, seg_buf); }
Seg程序
#include "Seg.h" void Seg_Tran(unsigned char *seg_string, unsigned char *seg_buf) { unsigned char i = 0; unsigned char j = 0; unsigned char temp; for(i = 0; i <= 7;i++,j++) { switch(seg_string[j]) { case '0': temp = 0xc0; break; case '1': temp = 0xf9; break; case '2': temp = 0xa4; break; case '3': temp = 0xb0; break; case '4': temp = 0x99; break; case '5': temp = 0x92; break; case '6': temp = 0x82; break; case '7': temp = 0xf8; break; case '8': temp = 0x80; break; case '9': temp = 0x90; break; case 'A': temp = 0x88; break; case 'C': temp = 0xc6; break; case 'P': temp = 0x8c; break; case ' ': temp = 0xff; break; //特殊情况 default: temp = 0xff; break; //默认 } if(seg_string[j+1] == '.')//判断小数点 { temp &= 0x7f; j++; } seg_buf[i] = temp; } } void Seg_Disp(unsigned char *seg_buf, unsigned char pos) { P0 = 1<<pos; P2 = P2 & 0X1F | 0xc0;//位码选通 P2 &= 0X1F; P0 = 0xff; P2 = P2 & 0X1F | 0xe0;//段码选通,数码管消隐 P2 &= 0X1F; P0 = seg_buf[pos]; P2 = P2 & 0X1F | 0xe0;//段码选通 P2 &= 0X1F; }
Led程序
void Led_Disp(unsigned char ucLed)
{
P0 = (~ucLed);
P2 = P2 & 0X1F | 0x80;//打开锁存器
P2 &= 0X1F;
}
Led_Proc函数
void Led_Proc(void) { if(Led_Slow_Down) return; Led_Slow_Down = 1; if(Dac_Mode==0)//DAC模式1下L1亮(在2021年3月模拟有类似题) { ucled1=0x01; } else ucled1=0x00;//在模式2下不亮 if(Runing_Mode==0)//在温度界面下L2亮 { ucled2=0x02; } else if(Runing_Mode==1)//在温度设置参数下L3亮 { ucled2=0x04; } else if(Runing_Mode==2)//在DAC电压显示界面L3亮 { ucled2=0x08; } ucLed=ucled1|ucled2;//将数码管与DAC电压输出模式下的LED结合 }
IIC总线驱动程序
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); } //等待应答 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; } void Pcf8591_Dac(unsigned char trans_dat) { IIC_Start(); IIC_SendByte(0x90); IIC_WaitAck(); IIC_SendByte(0x41); IIC_WaitAck(); IIC_SendByte(trans_dat); IIC_WaitAck(); IIC_Stop(); }
温度转换函数
void Delay_OneWire(unsigned int t) //STC89C52RC { t *= 12;//与c52的区别是12倍延时 while(t--); } //通过单总线向DS18B20写一个字节 void Write_DS18B20(unsigned char dat) { unsigned char i; for(i=0;i<8;i++) { DQ = 0; DQ = dat&0x01; Delay_OneWire(5); DQ = 1; dat >>= 1; } Delay_OneWire(5); } //从DS18B20读取一个字节 unsigned char Read_DS18B20(void) { unsigned char i; unsigned char dat; for(i=0;i<8;i++) { DQ = 0; dat >>= 1; DQ = 1; if(DQ) { dat |= 0x80; } Delay_OneWire(5); } return dat; } //DS18B20设备初始化 bit init_ds18b20(void) { bit initflag = 0; DQ = 1; Delay_OneWire(12); DQ = 0; Delay_OneWire(80); DQ = 1; Delay_OneWire(10); initflag = DQ; Delay_OneWire(5); return initflag; }//以上代码是底层函数,比赛会给 unsigned int rd_temperature(void) { unsigned char low,high; init_ds18b20(); Write_DS18B20(0xCC);//跳过ROM Write_DS18B20(0x44);//开始温度转换 init_ds18b20(); Write_DS18B20(0xCC); Write_DS18B20(0xBE);//读取高速寄存器 low = Read_DS18B20(); high = Read_DS18B20(); return ((high<<8)|low);//将高八位与低八位结合成为温度 }
定时器函数
void Timer1Init(void) //1毫秒@12.000MHz 定时器1
{
AUXR &= 0xBF; //定时器时钟12T模式
TMOD &= 0x0F; //设置定时器模式
TL1 = 0x18; //设置定时初值
TH1 = 0xFC; //设置定时初值
TF1 = 0; //清除TF1标志
TR1 = 1; //定时器1开始计时
ET1 = 1;
}
接下来附带几张开发板测试图
界面1温度显示界面
界面2温度参数设置界面
界面3DAC电压输出第一模式
界面3DAC电压输出第二模式
好了以上就是我本次参加蓝桥杯的个人代码了,由于本人没有学太深入有很多地方还是有点问题,这也是我第一次写文章,所以恳请路过的大佬多多指点下,先谢谢啦
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。