2018年“蓝桥杯” 第九届全国软件和信息技术专业人才大赛个人赛
单片机设计与开发项目
河南大学民生学院预选赛试题
“简易摄氏、华氏双显温度计”设计
设计功能要求:
1 上电自检,数码管LED全亮,3秒钟后黑屏,然后蜂鸣器响200mS;(25分)
2 按键S4,显示学号后四位;(15分)
3 按下S5,测温,即显示当前温度;【该代码段要求逐行注释】
再次按下S5,将温度显示为华氏温度。(25分)
4 按下S6,存储当前温度;(15分)
5 按下S7,显示存储温度;再次按下S7,将温度显示为华氏温度。(20分)
注:1温度显示保留小数点1位,显示格式位xx.xC 或xx.xF
2 华氏与摄氏的换算公式位:οF = ℃ × 1.8 + 32
3 自检阶段,按键无效
4 完成程序设计任务,并将工程文件保存在学号+姓名命名的文件夹中上交
拓展要求:断电重启后,存储温度值不丢失
成绩分两部分:现场测试成绩(占70%)+代码成绩(占30%)
程序:
主程序
#include "stc15f2k60s2.h" #include "onewire.h" #include "iic.h" // 0 1 2 3 4 5 6 7 8 9 unsigned char code tab[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90, // 灭 c f 0. 1. 2. 3. 4. 5. 6. 7. 8. 9. 0xff,0xc6,0x8e,0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10}; unsigned char dspbuf[8]={10,10,10,10,10,10,10,10}; unsigned char dspcom; unsigned char key_v,flag0,flag1,flag2; int i; int temper0,temper1,temper2,temper3; unsigned char keyscan(void); void display(void); void delay10ms(); void cls_buzz() { P2=0xa0; P0=0x00; P2=0x1f; } void on_led() //led and shumaguan { P2=0x80; P0=0x00; P2=0xe0; P0=0x00; P2=0xc0; P0=0xff; } void delay10ms() //@11.0592MHz { unsigned char i, j; i = 108; j = 145; do { while (--j); } while (--i); } void main() { cls_buzz(); on_led(); AUXR |= 0x80; //定时器时钟1T模式 TMOD &= 0xF0; //设置定时器模式 TL0 = 0xCD; //设置定时初值 TH0 = 0xD4; //设置定时初值 TF0 = 0; //清除TF0标志 // TR0 = 1; //定时器0开始计时 ET0 = 1; AUXR |= 0x40; //定时器时钟1T模式 TMOD &= 0x0F; //设置定时器模式 TL1 = 0xCD; //设置定时初值 TH1 = 0xD4; //设置定时初值 TF1 = 0; //清除TF1标志 TR1 = 1; //定时器1开始计时 ET1 = 1; EA = 1; while(1) { while(flag2) { key_v=keyscan(); if (key_v==4) { dspbuf[0]=3; dspbuf[1]=0; dspbuf[2]=6; dspbuf[3]=1; } if (key_v==5) { flag0++; if(flag0==3) { flag0=1; } } if (flag0==1) { temper0=temper_read()*10; dspbuf[4]=temper0/100; dspbuf[5]=temper0%100/10+13; dspbuf[6]=temper0%100%10; dspbuf[7]=11; } if (flag0==2) { temper1=(temper_read()*1.8+32)*10; dspbuf[4]=temper1/100; dspbuf[5]=temper1%100/10+13; dspbuf[6]=temper1%100%10; dspbuf[7]=12; } if (key_v==6) { write_eeprom(0x00,dspbuf[4]); write_eeprom(0x01,dspbuf[5]); write_eeprom(0x02,dspbuf[6]); write_eeprom(0x03,temper_read()); } if (key_v==7) { flag1++; if (flag1==3) { flag1=1; } if (flag1==1) { dspbuf[0]=3; dspbuf[1]=0; dspbuf[2]=6; dspbuf[3]=1; // temper2=read_eeprom(0x00)*10; dspbuf[0]=read_eeprom(0x00); dspbuf[1]=read_eeprom(0x01); dspbuf[2]=read_eeprom(0x02); dspbuf[3]=11; } if (flag1==2) { dspbuf[0]=3; dspbuf[1]=0; dspbuf[2]=6; dspbuf[3]=1; temper3=(read_eeprom(0x03)*1.8+32)*10; dspbuf[0]=temper3/100; dspbuf[1]=temper3%100/10+13; dspbuf[2]=temper3%100%10; dspbuf[3]=12; } } } } } void timer0(void) interrupt 1 { display(); } void timer1(void) interrupt 3 { i++; if (i==3000) { P2=0x80; P0=0xff; P2=0x1f; P2=0xa0; P0=0x40; P2=0x1f; TR0=1; } if (i==3200) { cls_buzz(); TR1=0; flag2=1; } } void display(void) { P2=0xe0; P0=0xff; P2=0x1f; P0=1<<dspcom; P2=0xc0; P2=0x1f; P2=0xe0; P0=tab[dspbuf[dspcom]]; P2=0x1f; if (++dspcom==8) { dspcom=0; } } unsigned char keyscan(void) { unsigned char key=0; unsigned char GPIO; GPIO=P3; GPIO&=0x0f; if (GPIO!=0x0f) { delay10ms(); GPIO=P3; GPIO&=0x0f; if (GPIO!=0x0f) { switch(GPIO) { case 0x0e:key=7;break; case 0x0d:key=6;break; case 0x0b:key=5;break; case 0x07:key=4;break; default:break; } while(GPIO!=0x0f) { GPIO=P3; GPIO&=0x0f; } } } return key; }
IIC模块
/* 程序说明: IIC总线驱动程序 软件环境: Keil uVision 4.10 硬件环境: CT107单片机综合实训平台(12MHz) 日 期: 2011-8-9 */ #include "iic.h" //总线启动条件 void IIC_Start(void) { SDA = 1; SCL = 1; somenop; SDA = 0; somenop; SCL = 0; } //总线停止条件 void IIC_Stop(void) { SDA = 0; SCL = 1; somenop; SDA = 1; } //应答位控制 void IIC_Ack(unsigned char ackbit) { if(ackbit) { SDA = 0; } else { SDA = 1; } somenop; SCL = 1; somenop; SCL = 0; SDA = 1; somenop; } //等待应答 bit IIC_WaitAck(void) { SDA = 1; somenop; SCL = 1; somenop; if(SDA) { SCL = 0; IIC_Stop(); return 0; } else { SCL = 0; return 1; } } //通过I2C总线发送数据 void IIC_SendByte(unsigned char byt) { unsigned char i; for(i=0;i<8;i++) { if(byt&0x80) { SDA = 1; } else { SDA = 0; } somenop; SCL = 1; byt <<= 1; somenop; SCL = 0; } } //从I2C总线上接收数据 unsigned char IIC_RecByte(void) { unsigned char da; unsigned char i; for(i=0;i<8;i++) { SCL = 1; somenop; da <<= 1; if(SDA) da |= 0x01; SCL = 0; somenop; } return da; } //向EEPROM里写数据(地址)/ void write_eeprom(unsigned char add,unsigned char date) { IIC_Start(); IIC_SendByte(0xa0);//发送方式字 1010 0000 激活该器件写操作 IIC_WaitAck(); IIC_SendByte(add); IIC_WaitAck(); IIC_SendByte(date); IIC_WaitAck(); IIC_Stop(); delay10ms(); } //从EEPROM里读数据(地址)/ unsigned char read_eeprom(unsigned char add) { unsigned char date; IIC_Start(); IIC_SendByte(0xa0);//发送方式字 1010 0000 激活该器件写操作 IIC_WaitAck(); IIC_SendByte(add); IIC_WaitAck(); IIC_Start(); IIC_SendByte(0xa1);//发送方式字 1010 0001 激活该器件读操作 IIC_WaitAck(); date=IIC_RecByte(); IIC_Ack(0); IIC_Stop(); return date; }