既然大家想要了解十一届蓝桥杯单片机国赛,那小编话不多说,大家先来看看十一届单片机的程序设计试题吧。
相信大家看完试题后有了大概的思路了,十一届国赛试题有基本的三大块数码管、按键、LED,外加DS1302、i2c、与DS18B20。现在小编在这里奉上个人的代码。
主函数main.c
#include "config.h"
extern unsigned char mod4 ,mod5,segbuff[],hour,minute,second,flag_v;//S4 界面控制 显示界面
extern unsigned int temp,flag_L31;//温度存取 电压存取
unsigned char light = 0;//光照读取
unsigned char count_temp = 0,count_v = 0;//计时读取温度 计时读取电压
unsigned int cc = 0,old_liht = 0,count_L3 = 0;//计时读取温度 保存上次的光敏 暗状态计时
extern unsigned int k_temp1,k_hour1,k_led1,k_temp,k_hour,k_led,date_v;
float temp232 = 0;
void main(){
unsigned char key_num = 20;
sysinit();
init_ds1302(0x16,0x59,0x50);
Timer1Init();
while(1){
key_num = scankbd();
switch(key_num){
case 0://切换数据界面与参数界面
if(++mod4 == 2) mod4 = 0;
break;
case 1://切换显示
if(++mod5 == 3) mod5 = 0;
break;
case 4://参数加
if(mod4 == 1) S8();
break;
case 5://参数减
if(mod4 == 1) S9();
break;
default:
break;
}
if(cc >= 200){//读取温度
temp = rd_temperature();
cc = 0;
}
if(count_v == 50){//获取光照
light = adc(1);
temp232 = (float)(light/51.0);
date_v = temp232*100;
if(light>130){
flag_v = 1;//亮状态
}else{
flag_v = 0;//暗状态
}
count_v = 0;
}
if(mod4 == 0){k_hour = k_hour1;k_temp = k_temp1;k_led = k_led1;}
read_ds1302();//获取时间
S4();//判断界面
}
}
void tiem1() interrupt 3{
cc++;
segs();
count_v++;
if(flag_v == 0){
count_L3++;
}else{
count_L3 = 0;
}
ledpaly();
}
系统各个模块的函数配置函数
config.c
该文件主要写一些用于配置系统工作的函数,如按系统初始化函数、键扫描函数、数码管显示函数、各个显示函数等。
#include "config.h"
sbit L1 = P0^0;
sbit L2 = P0^1;
sbit L3 = P0^2;
sbit L4 = P0^3;
sbit L5 = P0^4;
sbit L6 = P0^5;
sbit L7 = P0^6;
sbit L8 = P0^7;
sbit relay = P0^4;
sbit buzzer = P0^6;
#define kbd_io P3
#define kbd_maskrow 0x0f
#define state_0 0
#define state_1 1
#define state_2 2
unsigned char segbuff[] = {10,10,10,10,10,10,10,10};
unsigned char segtab[] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xbf,0xff,
0xc0&0x7f,0xf9&0x7f,0xa4&0x7f,0xb0&0x7f,0x99&0x7f,0x92&0x7f,0x82&0x7f,0xf8&0x7f,0x90&0x7f,0x90&0x7f,0xbf,0xff,
0xc6,0x86,0x8c};// C E P
unsigned char mod5 = 0;//S5 显示控制
unsigned int temp = 0,k_temp = 25,k_hour = 0x17,k_led = 4,date_v = 0;//存放温度 存放分压值 温度参数 小时参数 LED参数
unsigned char flag_v = 0,flag_L31 = 0,hour1 = 0;//显示亮暗(1暗 0亮)
unsigned char mod4 = 0,hour_temp = 0;//S4 界面控制
unsigned int k_temp1 = 25,k_hour1 = 17,k_led1 = 4;
extern unsigned char hour,minute,second;//时 分 秒
extern unsigned int count_L3;
void sysinit(){
P2 = P2&0x1f|0x80;P0 = 0xff; P2 &= 0x1f;
P2 = P2&0x1f|0xa0;relay = 0;buzzer = 0;P2 &= 0x1f;
P2 = P2&0x1f|0xe0;P0 = 0xff;P2 &= 0x1f;
P2 = P2&0x1f|0xc0;P0 = 0x00;P2 &= 0x1f;
}
void segs(){
static unsigned char segaddr = 0;
P2 = P2&0x1f|0xe0;P0 = 0xff;P2 &= 0x1f;
P2 = P2&0x1f|0xc0;P0 = 1<<segaddr;P2 &= 0x1f;
P2 = P2&0x1f|0xe0;P0 = segtab[segbuff[segaddr]];P2 &= 0x1f;
if(++segaddr == 8) segaddr = 0;
}
unsigned char scankbd(){
unsigned char key_num = 20;
static unsigned char kbd_state = 0;
unsigned char kbd_press;
switch(kbd_state){
case state_0:
kbd_io = 0x0f;P42 = 0;P44 = 0;kbd_press = kbd_io;
if(kbd_press != kbd_maskrow){
kbd_state = state_1;
}
break;
case state_1:
kbd_press = kbd_io;
if(kbd_press != kbd_maskrow){
if((kbd_io&0x08)==0) key_num = 0;
if((kbd_io&0x04)==0) key_num = 1;
if((kbd_io&0x02)==0) key_num = 2;
if((kbd_io&0x01)==0) key_num = 3;
kbd_io = 0xf0;P44 = 1;P42 = 1;
if(P44 == 0) key_num += 0;
if(P42 == 0) key_num += 4;
if((kbd_io&0x20)==0) key_num += 8;
if((kbd_io&0x10)==0) key_num += 12;
kbd_state = state_2;
}else{
kbd_state = state_0;
}
break;
case state_2:
kbd_io = 0x0f;P42 = 0;P44 = 0;kbd_press = kbd_io;
if(kbd_press == kbd_maskrow){
kbd_state = state_0;
}
break;
default :
break;
}
return key_num;
}
void S4(){//界面控制 数据界面 参数界面
switch(mod4){
case 0://数据界面
S51();
break;
case 1://参数界面
S52();
break;
}
}
void S51(){//显示界面切换 时间 温度 亮度状态
switch(mod5){//显示时间
case 0:
segbuff[0] = hour/16;
segbuff[1] = hour%16;
segbuff[2] = 10;
segbuff[3] = minute/16;
segbuff[4] = minute%16;
segbuff[5] = 10;
segbuff[6] = second/16;
segbuff[7] = second%16;
break;
case 1://显示温度
segbuff[0] = 24;
segbuff[1] = 10;
segbuff[2] = 10;
segbuff[3] = 10;
segbuff[4] = 10;
segbuff[5] = temp/1000;
segbuff[6] = temp%1000/100+12;
segbuff[7] = temp%1000%100/10;
break;
case 2://显示分压 亮度
segbuff[0] = 25;
segbuff[1] = 10;
segbuff[2] = date_v/100+12;
segbuff[3] = date_v/10%10;
segbuff[4] = date_v%10;
segbuff[5] = 10;
segbuff[6] = 10;
segbuff[7] = flag_v;
break;
}
}
void S52(){//显示参数
switch(mod5){//显示时间参数
case 0:
segbuff[0] = 26;
segbuff[1] = 1;
segbuff[2] = 10;
segbuff[3] = hour_temp/10;
segbuff[4] = hour_temp%10;
segbuff[5] = 10;
segbuff[6] = k_hour/10;
segbuff[7] = k_hour%10;
break;
case 1://显示温度参数
segbuff[0] = 26;
segbuff[1] = 2;
segbuff[2] = 10;
segbuff[3] = 10;
segbuff[4] = 10;
segbuff[5] = 10;
segbuff[6] = k_temp/10;
segbuff[7] = k_temp%10;
break;
case 2://显示指示灯参数
segbuff[0] = 26;
segbuff[1] = 3;
segbuff[2] = 10;
segbuff[3] = 10;
segbuff[4] = 10;
segbuff[5] = 10;
segbuff[6] = 10;
segbuff[7] = k_led%10;
break;
}
}
//mod5 0表示小时参数 1表示温度参数 2表示led参数
void S8(){//当前参数减1
switch(mod5){
case 0:
if(--k_hour1 >= 24) k_hour1 = 23;
break;
case 1:
if(--k_temp1 >=100) k_temp1 = 99;
break;
case 2:
if(--k_led1 <= 3) k_led1 = 8;
break;
}
}
void S9(){//当前参数加1
switch(mod5){
case 0:
if(++k_hour1 >= 24) k_hour1 = 0;
break;
case 1:
if(++k_temp1 >=100) k_temp1 = 0;
break;
case 2:
if(++k_led1 >=9) k_led1 = 4;
break;
}
}
void ledpaly(){
P2 = P2&0x1f|0x80;P0 = 0xff;P2 &= 0x1f;
hour_temp = hour/16*10+hour%16;
if(hour_temp>=k_hour || hour_temp<=8){//条件不够
P2 = P2&0x1f|0x80;L1 = 0;P2 &= 0x1f;//L1亮
}else{
P2 = P2&0x1f|0x80;L1 = 1;P2 &= 0x1f;//L1灭
}
if(temp <= k_temp*100){
P2 = P2&0x1f|0x80;L2 = 0;P2 &= 0x1f;//L2亮
}else{
P2 = P2&0x1f|0x80;L2 = 1;P2 &= 0x1f;//L2灭
}
if(count_L3 >= 3000){
P2 = P2&0x1f|0x80;L3 = 0;P2 &= 0x1f;//L3亮
}else{
P2 = P2&0x1f|0x80;L3 = 1;P2 &= 0x1f;//L3灭
}
if(flag_v == 0){
switch(k_led){//选择亮L4-L8
case 4: P2 = P2&0x1f|0x80;L4 = 0;P2 &= 0x1f;
break;
case 5: P2 = P2&0x1f|0x80;L5 = 0;P2 &= 0x1f;
break;
case 6: P2 = P2&0x1f|0x80;L6 = 0;P2 &= 0x1f;
break;
case 7: P2 = P2&0x1f|0x80;L7 = 0;P2 &= 0x1f;
break;
case 8: P2 = P2&0x1f|0x80;L8 = 0;P2 &= 0x1f;
break;
default: break;
}
}
}
void Timer1Init(void) //1毫秒@12.000MHz
{
AUXR &= 0xBF; //定时器时钟12T模式
TMOD &= 0x0F; //设置定时器模式
TL1 = 0x18; //设置定时初始值
TH1 = 0xFC; //设置定时初始值
TF1 = 0; //清除TF1标志
TR1 = 1; //定时器1开始计时
EA = 1;
ET1 = 1;
}
iic.c模块
iic.c
IIC代码也可以自行在官方资源包中提取,但是需要注意细节,某些地方可能会出现一两个bug,
/*
程序说明: IIC总线驱动程序
软件环境: Keil uVision 4.10
硬件环境: CT107单片机综合实训平台 8051,12MHz
日 期: 2011-8-9
*/
#include <STC15F2K60S2.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;
}
unsigned char adc(unsigned char add){
unsigned char dat = 0;
IIC_Start();
IIC_SendByte(0x90);
IIC_WaitAck();
IIC_SendByte(add);
IIC_WaitAck();
IIC_Stop();
IIC_Start();
IIC_SendByte(0x91);
IIC_WaitAck();
dat = IIC_RecByte();
IIC_SendAck(1);
IIC_Stop();
return dat;
}
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);
unsigned char adc(unsigned char add);
#endif
ds1302模块
ds1302.c
ds1302的基本函数官方也提供了,目前来看没有留下过“坑”,大家可以放心使用。
/*
程序说明: DS1302驱动程序
软件环境: Keil uVision 4.10
硬件环境: CT107单片机综合实训平台 8051,12MHz
日 期: 2011-8-9
*/
#include <STC15F2K60S2.h>
#include "intrins.h"
#include "ds1302.h"
sbit SCK=P1^7;
sbit SDA=P2^3;
sbit RST = P1^3; // DS1302复位
void Write_Ds1302(unsigned char temp)
{
unsigned char i;
for (i=0;i<8;i++)
{
SCK=0;
SDA=temp&0x01;
temp>>=1;
SCK=1;
}
}
void Write_Ds1302_Byte( unsigned char address,unsigned char dat )
{
RST=0; _nop_();
SCK=0; _nop_();
RST=1; _nop_();
Write_Ds1302(address);
Write_Ds1302(dat);
RST=0;
}
unsigned char Read_Ds1302_Byte ( unsigned char address )
{
unsigned char i,temp=0x00;
RST=0; _nop_();
SCK=0; _nop_();
RST=1; _nop_();
Write_Ds1302(address);
for (i=0;i<8;i++)
{
SCK=0;
temp>>=1;
if(SDA)
temp|=0x80;
SCK=1;
}
RST=0; _nop_();
SCK=0; _nop_();
SCK=1; _nop_();
SDA=0; _nop_();
SDA=1; _nop_();
return (temp);
}
unsigned char hour = 0,minute = 0,second = 0;
void init_ds1302(unsigned char h,unsigned char m,unsigned char s){
Write_Ds1302_Byte(0x8e,0);
Write_Ds1302_Byte(0x84,h);
Write_Ds1302_Byte(0x82,m);
Write_Ds1302_Byte(0x80,s);
Write_Ds1302_Byte(0x8e,0x80);
}
void read_ds1302(){
hour = Read_Ds1302_Byte(0x85);
minute = Read_Ds1302_Byte(0x83);
second = Read_Ds1302_Byte(0x81);
}
ds1302.h
#ifndef __DS1302_H
#define __DS1302_H
void Write_Ds1302(unsigned char temp);
void Write_Ds1302_Byte( unsigned char address,unsigned char dat );
unsigned char Read_Ds1302_Byte( unsigned char address );
void init_ds1302(unsigned char h,unsigned char m,unsigned char s);
void read_ds1302();
#endif
onewire模块
onewire.c
onewire系列的基本函数官方也有提供,大家可自行提取,目前来看,代码也是可以直接使用的,不用担心出现bug。
/*
程序说明: 单总线驱动程序
软件环境: Keil uVision 4.10
硬件环境: CT107单片机综合实训平台(外部晶振12MHz) STC89C52RC单片机
日 期: 2011-8-9
*/
#include "STC15F2K60S2.h"
#include "onewire.h"
sbit DQ = P1^4; //单总线接口
//单总线延时函数
void Delay_OneWire(unsigned int t) //STC89C52RC
{
unsigned char i;
while(t--){
for(i =0;i<12;i++)
;
}
}
//通过单总线向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;
unsigned int result;
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0x44);
Delay_OneWire(200);
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0xbe);
low = Read_DS18B20();
high = Read_DS18B20();
result = high&0x0f;
result <<= 8;
result |= low;
result = result*6.25;//0.0625*100;
return result;
}
onewire.h
#ifndef __ONEWIRE_H
#define __ONEWIRE_H
unsigned int rd_temperature(void);
void Delay_OneWire(unsigned int t);
void Write_DS18B20(unsigned char dat);
unsigned char Read_DS18B20(void);
bit init_ds18b20(void);
#endif