蓝桥杯省赛模板
本模板主要参考《“蓝桥杯”全国软件和信息技术专业人才大赛(电子类)实训指导书》,并依据自己习惯编写而成。
User
main.c
#include "stdio.h"
#include "tim.h"
#include "bsp_init.h"
#include "bsp_led.h"
#include "bsp_seg.h"
#include "bsp_key.h"
#include "bsp_ds1302.h"
#include "bsp_iic.h"
#include "bsp_onewire.h"
#include "bsp_ultrasonic.h"
/******函数声明******/
void KEY_Proc(void);
void SEG_Proc(void);
void LED_Proc(void);
/******变量定义******/
//LED专用
uchar LED = 0x00;
//SEG专用
uchar seg_string[10];
uchar seg_buf[8];
uchar seg_pos;
//KEY专用
uchar key_value;
uchar key_down;
uchar key_old;
//减速专用
uchar key_delay;
uchar seg_delay;
uchar led_delay;
//滴答变量
uint ms_tick;
uint s_tick;
//DS1302专用
uchar RTC[3];
//at24c02专用
uchar rom_string[8];
//根据代码需求进行变化
/******主函数******/
void main(void)
{
cls_peripheral();//关闭外设
Timer1Init();
EA = 1;
//EEPROM读取
EEPROM_Read(rom_string,0x00,1);
while(1)
{
KEY_Proc();
SEG_Proc();
LED_Proc();
}
}
/******定时器1中断服务函数******/
void timer1(void) interrupt 3
{
if (++key_delay == 10) key_delay = 0;
if (++seg_delay == 200) key_delay = 0;
if (++led_delay == 100) key_delay = 0;
//滴答变量
//数码管显示
SEG_Disp(seg_buf,seg_pos);
if (++seg_pos == 8) seg_pos = 0;
//LED显示
LED_Disp(LED);
}
/*****KEY处理函数******/
void KEY_Proc(void)
{
if (key_delay) return;
key_delay = 1;
//键值获取
key_value = KEY_READ_KBD();
key_down = key_value & (key_value ^ key_old);
key_old = key_value;
//根据代码需求进行改变
}
/*****SEG处理函数******/
void SEG_Proc(void)
{
if (seg_delay) return;
seg_delay = 1;
//SEG内容
//SEG编码
SEG_Tran(seg_string, seg_buf);
}
/*****LED处理函数******/
void LED_Proc(void)
{
if (led_delay) return;
led_delay = 1;
//根据代码需求进行改变
}
Sys
tim.c
#include "tim.h"
void Timer1Init(void) //1毫秒@12.000MHz
{
AUXR &= 0xBF; //定时器时钟12T模式
TMOD &= 0x0F; //设置定时器模式
TL1 = 0x18; //设置定时初值
TH1 = 0xFC; //设置定时初值
TF1 = 0; //清除TF1标志
TR1 = 1; //定时器1开始计时
ET1 = 1;
}
void Timer0Init_Freq(void)
{
TMOD |= 0x04;
TL0 = 0;
TH0 = 0;
TR0 = 1;
}
uart.c
#include "uart.h"
void UartInit(void) //4800bps@12.000MHz
{
SCON = 0x50; //8位数据,可变波特率
AUXR |= 0x01; //串口1选择定时器2为波特率发生器
AUXR |= 0x04; //定时器2时钟为Fosc,即1T
T2L = 0x8F; //设定定时初值
T2H = 0xFD; //设定定时初值
AUXR |= 0x10; //启动定时器2
ES = 1; //一定一定不要忘记开中断!
}
//发送一个字节
void Uart_Sendbyte(uchar byte)
{
SBUF = byte;
while(TI == 0);
TI = 0;
}
//发送一个字符串
void Uart_Sendstring(uchar *string)
{
while(*string != '\0')
{
Uart_Sendbyte(*string);
string++;
}
}
Driver
bsp_init.c
#include "bsp_init.h"
void cls_peripheral(void)
{
P0 = 0xFF;
P2 = P2 & 0x1F | 0x80;
P2 = P2 & 0x1F;
P0 = 0x00;
P2 = P2 & 0x1F | 0xa0;
P2 = P2 & 0x1F;
}
void UartInit(void) //9600bps@12.000MHz
{
SCON = 0x50; //8位数据,可变波特率
AUXR |= 0x01; //串口1选择定时器2为波特率发生器
AUXR &= 0xFB; //定时器2时钟为Fosc/12,即12T
T2L = 0xE6; //设定定时初值
T2H = 0xFF; //设定定时初值
AUXR |= 0x10; //启动定时器2
}
//开关蜂鸣器和继电器的部分代码
void open_beep(void)
{
P0 = 0x40;
P2 = P2 & 0x1F | 0xA0;
P2 = P2 & 0x1F;
}
void close_beep(void)
{
P0 = 0x00;
P2 = P2 & 0x1F | 0xA0;
P2 = P2 & 0x1F;
}
void open_relay(void)
{
P0 = 0x10;
P2 = P2 & 0x1F | 0xA0;
P2 = P2 & 0x1F;
}
bsp_init.h
#ifndef _BSP_INIT_H
#define _BSP_INIT_H
#ifndef uchar
#define uchar unsigned char
#endif
#ifndef uint
#define uint unsigned int
#endif
#include "STC15F2K60S2.H"
void cls_peripheral(void);
void UartInit(void);
#endif
bsp_led.c
#include "bsp_led.h"
void LED_Disp(uchar LED)
{
P0 = ~LED;
P2 = P2 & 0x1F | 0x80;
P2 = P2 & 0x1F;
}
bsp_seg.c
#include "bsp_seg.h"
void SEG_Disp(uchar *seg_buf, uchar seg_pos)
{
P0 = 0xFF;
P2 = P2 & 0x1F | 0xe0;
P2 = P2 & 0x1F;
P0 = 1 << seg_pos;
P2 = P2 & 0x1F | 0xc0;
P2 = P2 & 0x1F;
P0 = seg_buf[seg_pos];
P2 = P2 & 0x1F | 0xe0;
P2 = P2 & 0x1F;
}
void SEG_Tran(uchar *seg_string, uchar *seg_buf)
{
uchar i,j,temp;
for (i=0,j=0;i<8;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 'C': temp = 0xc6; break;
case '-': temp = 0xbf; break;
case ' ': temp = 0xff; break;
default: temp = 0xff;
}
if (seg_string[j+1] == '.')
{
temp = temp & 0x7F;
j++;
}
seg_buf[i] = temp;
}
}
bsp_key.c
#include "bsp_key.h"
uchar KEY_READ_BIN(void)
{
uchar key_value;
if (P30 == 0) key_value = 7;
else if (P31 == 0) key_value = 6;
else if (P32 == 0) key_value = 5;
else if (P33 == 0) key_value = 4;
else key_value = 0;
return key_value;
}
uchar KEY_READ_KBD(void)
{
uchar key_value;
uint key_new;
P44 = 0; P42 = 1; P35 = 1; P34 = 1;
key_new = P3 & 0x0F;
P44 = 1; P42 = 0; P35 = 1; P34 = 1;
key_new = (P3 & 0x0F) | (key_new << 4);
P44 = 1; P42 = 1; P35 = 0; P34 = 1;
key_new = (P3 & 0x0F) | (key_new << 4);
P44 = 1; P42 = 1; P35 = 1; P34 = 0;
key_new = (P3 & 0x0F) | (key_new << 4);
switch(~key_new)
{
case 0x8000: key_value = 4; break;
case 0x4000: key_value = 5; break;
case 0x2000: key_value = 6; break;
case 0x1000: key_value = 7; break;
case 0x0800: key_value = 8; break;
case 0x0400: key_value = 9; break;
case 0x0200: key_value = 10; break;
case 0x0100: key_value = 11; break;
case 0x0080: key_value = 12; break;
case 0x0040: key_value = 13; break;
case 0x0020: key_value = 14; break;
case 0x0010: key_value = 15; break;
case 0x0008: key_value = 16; break;
case 0x0004: key_value = 17; break;
case 0x0002: key_value = 18; break;
case 0x0001: key_value = 19; break;
default: key_value = 0;
}
return key_value;
}
bsp_onewire.h
#include "bsp_onewire.h"
sbit DQ = P1^4; //单总线接口
//单总线延时函数
void Delay_OneWire(unsigned int t) //STC89C52RC
{
t=t * 12;
while(t--);
}
void delay_us(void)
{
uchar i = 30;
while(--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;
delay_us();
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;
}
uint READ_Tempature(void)
{
uchar low,high;
init_ds18b20();
Write_DS18B20(0xCC);
Write_DS18B20(0x44);
init_ds18b20();
Write_DS18B20(0xCC);
Write_DS18B20(0xBE);
low = Read_DS18B20();
high = Read_DS18B20();
return (high<<8) | low;
}
bsp_ds1302
#include <bsp_ds1302.h>
#include <intrins.h>
sbit SCK=P1^7;
sbit SDA=P2^3;
sbit RST = P1^3; // DS1302复位
//读取RTC
void RTC_READ(uchar *RTC)
{
uchar temp;
temp = Read_Ds1302_Byte(0x85);
RTC[0] = (temp>>4)*10 + temp&0x0F;
temp = Read_Ds1302_Byte(0x83);
RTC[1] = (temp>>4)*10 + temp&0x0F;
temp = Read_Ds1302_Byte(0x81);
RTC[2] = (temp>>4)*10 + temp&0x0F;
}
//设置RTC
void RTC_SET(uchar *RTC)
{
uchar temp;
Write_Ds1302_Byte(0x8e, 0);
temp = ((RTC[0]/10)<<4) | (RTC[0]%10);
Write_Ds1302_Byte(0x84,temp);
temp = ((RTC[1]/10)<<4) | (RTC[1]%10);
Write_Ds1302_Byte(0x82,temp);
temp = ((RTC[2]/10)<<4) | (RTC[2]%10);
Write_Ds1302_Byte(0x80,temp);
Write_Ds1302_Byte(0x8e, 0x80);
}
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);
}
bsp_iic.c
#include "bsp_iic.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;
}
//读ROM
void EEPROM_Read(uchar *rom_string, uchar addr, uchar num)
{
IIC_Start();
IIC_SendByte(0xa0);
IIC_WaitAck();
IIC_SendByte(addr);
IIC_WaitAck();
IIC_Start();
IIC_SendByte(0xa1);
IIC_WaitAck();
while(num--)
{
*rom_string++ = IIC_RecByte();
if (num)
IIC_SendAck(0);
else
IIC_SendAck(1);
}
}
//写ROM
void EEPROM_Write(uchar *rom_string, uchar addr, uchar num)
{
IIC_Start();
IIC_SendByte(0xa0);
IIC_WaitAck();
IIC_SendByte(addr);
IIC_WaitAck();
while(num--)
{
IIC_SendByte(*rom_string++);
IIC_WaitAck();
IIC_Delay(200);
}
IIC_Stop();
IIC_Delay(200);
}
//读PCF8591,ADC
uchar PCF8591_ADC(uchar channel)
{
uchar temp;
IIC_Start();
IIC_SendByte(0x90);
IIC_WaitAck();
IIC_SendByte(channel);
IIC_WaitAck();
IIC_Start();
IIC_SendByte(0x91);
IIC_WaitAck();
temp = IIC_RecByte();
IIC_SendAck(1);
IIC_Stop();
return temp;
}
//写PCF8591,DAC
void PCF8591_DAC(uchar dat)
{
IIC_Start();
IIC_SendByte(0x90);
IIC_WaitAck();
IIC_SendByte(0x42);
IIC_WaitAck();
IIC_SendByte(dat);
IIC_WaitAck();
IIC_Stop();
}
bsp_ultrasonic.c
#include "bsp_ultrasonic.h"
sbit TX = P1 ^ 0;
sbit RX = P1 ^ 1;
void Timer0Init(void) //13微秒@12.000MHz
{
AUXR &= 0x7F; //定时器时钟12T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0xF3; //设置定时初值
TH0 = 0xFF; //设置定时初值
TF0 = 0; //清除TF0标志
TR0 = 0; //定时器0开始计时
}
uchar Wave_Recv(void)
{
uchar distance, num = 10;
//超声波发送代码
TX = 0;
TL0 = 0xF3; //设置定时初值
TH0 = 0xFF; //设置定时初值
TR0 = 1;
while(num--)
{
while(!TF0);
TX ^= 1;
TF0 = 0;
}
//超声波接收代码
TR0 = 0;
TL0 = 0;
TH0 = 0;
TR0 = 1;
while(RX && (!TF0));
TR0 = 0;
if (TF0)
{
TF0 = 0;
distance = 255;
}
else
distance = ((TH0<<8)+TL0)*0.017*1.085;
return distance;## 标题
}
其他部分
频率测量
//定时器1中断函数部分
if (++freq_num >= 1000)
{
TR0 = 0;
freq = (TH0<<8)|TL0;
freq_num = 0;
Timer0Init_Freq();
}
串口部分
//串口专用变量
uchar uart_send_string[12];
uchar uart_recv_string[12];
uchar uart_recv_num;
//串口中断
void Uart_ISR(void) interrupt 4
{
if (RI)
{
uart_recv_string[uart_recv_num] = SBUF;
uart_recv_num++;
RI = 0;
}
}
//串口处理函数
void UART_Proc(void)
{
if (uart_delay) return;
uart_delay = 1;
if ((uart_recv_string[uart_recv_num-1] == '\n') && (uart_recv_string[uart_recv_num-2] == '\r'))
{
if (uart_recv_num == 4)
{
if((uart_recv_string[0] == 'S') && (uart_recv_string[1] == 'T'))
{
uart_recv_num = 0;
sprintf(uart_send_string, "had recv ST\r\n");
Uart_Sendstring(uart_send_string);
}
}
else
{
uart_recv_num = 0;
sprintf(uart_send_string, "ERROR\r\n");
Uart_Sendstring(uart_send_string);
}
}
}