蓝桥杯单片机——第十二届蓝桥杯单片机第一场省赛
一、赛题分析
前两天实验室的学妹把开发板还给我了,刚好今天没什么事做,就来做做今天的省赛题目。 在下是参加的去年的蓝桥杯单片机组,今年也刚参加的嵌入式组的省赛,已经好几个月没有摸单片机的板子了,以为会很生疏,看了一下之前的代码,然后做了一下今年的赛题,发现很快就找回感觉了。发现单片机组相对于嵌入式组确实要简单得多。 真的不难呀,大家一定要上手把几个基础模块过一遍,然后做两三套赛题,进决赛都挺容易的,相信我。
这一届的赛题也就中规中矩吧,已经完了前几届赛题的难度,总之这一届的还是偏简单。除了基础的数码管显示,矩阵键盘,LED之外,要是临近比赛,连这些都没有熟悉的画,自己去面壁思过吧。除此之外还考察了PCF8591的DAC功能和DS18B20。要说稍微有点难度的就是矩阵键盘和DS18B20的小数显示了吧,因为可能有些人偷懒根本就没有看过这两个部分。至于PCF8591的DAC相较于ADC简单得多,没有看过的,看一下程序应该就懂了,完整的程序可以参考第三部分。
二、问题总结
发现没有什么问题可以总结的,都不难…
三、代码
#include "STC15F2K60S2.h"
#include "onewire.h"
#include "iic.h"
#define u8 unsigned char
#define u16 unsigned int
#define TEMP_INTERFACE 0
#define DAC_INTERFACE 1
#define SETTING_INTERFACE 2
#define get() (P3 & 0X3F) | ((P4 & 0X10) << 3) | ((P4 & 0X04) << 4)
u8 code TAB[] = {
0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xbf,0xff,0xc6,0x8c,0x88};
u8 disbuf[] = {
0,1,2,3,4,5,6,7,8};
u8 smg_cnt = 0;
u8 key_buf = 0;
u16 sec_tick = 0;
u8 sec_cnt = 0;
u8 interface = 0;
u8 temperature_para = 25;
u8 temperature_para_temp = 25;
bit mode = 0;
float volt = 3.25;
float temperature = 0.0;
void write_pcf8591(unsigned char dat)
{
IIC_Start();
IIC_SendByte(0x90);
IIC_WaitAck();
IIC_SendByte(0x40);
IIC_WaitAck();
IIC_SendByte(dat);
IIC_WaitAck();
IIC_Stop();
}
float read_temperature(void)
{
unsigned char high,low;
unsigned int temp;
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0x44);
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0xbe);
low = Read_DS18B20();
high = Read_DS18B20();
temp = high;
temp <<= 8;
temp |= low;
return temp * 0.0625;
}
void Delay5ms() //@12.000MHz
{
unsigned char i, j;
i = 59;
j = 90;
do
{
while (--j);
} while (--i);
}
void set_port(u8 p2,u8 p0)
{
P2 = (P2 & 0x1F) | p2; // 使能74HC573,与上0x1F是为了不影响其他的端口
P0 = p0;
P2 &= 0x1F; // 将数据锁存
}
void allinit(void)
{
set_port(0x80,0xFF); // 关闭所有LED
set_port(0xA0,0x00); // 关闭继电器,蜂鸣器等外设
set_port(0xC0,0x00); // 关闭数码管位选
set_port(0xE0,0x00); // 关闭数码管段选
}
void display(void)
{
if(interface == TEMP_INTERFACE)
{
disbuf[1] = 12;
disbuf[2] = 11;
disbuf[3] = 11;
disbuf[4] = 11;
disbuf[5] = (u16)(temperature * 100) / 1000;
disbuf[6] = (u16)(temperature * 100) / 100 % 10;
disbuf[7] = (u16)(temperature * 100) / 10 % 10;
disbuf[8] = (u16)(temperature * 100) / 1000 % 10;
}
else if(interface == SETTING_INTERFACE)
{
disbuf[1] = 13;
disbuf[2] = 11;
disbuf[3] = 11;
disbuf[4] = 11;
disbuf[5] = 11;
disbuf[6] = 11;
disbuf[7] = temperature_para_temp / 10;
disbuf[8] = temperature_para_temp % 10;
}
else if(interface == DAC_INTERFACE)
{
disbuf[1] = 14;
disbuf[2] = 11;
disbuf[3] = 11;
disbuf[4] = 11;
disbuf[5] = 11;
disbuf[6] = (u16)(volt * 100) / 100;
disbuf[7] = (u16)(volt * 100) / 10 % 10;
disbuf[8] = (u16)(volt * 100) % 10;
}
}
void Timer2Init(void) //1毫秒@12.000MHz
{
AUXR |= 0x04; //定时器时钟1T模式
T2L = 0x20; //设置定时初值
T2H = 0xD1; //设置定时初值
AUXR |= 0x10; //定时器2开始计时
}
void KBD(void)
{
u8 key_temp ;
P3 = 0X0F; P44 = 0; P42 = 0;
key_temp = get();
P3 = 0XF0; P44 = 1; P42 = 1;
key_temp |= get();
if(key_temp != 0xff && !key_buf)
{
Delay5ms();
P3 = 0X0F; P44 = 0; P42 = 0;
key_temp = get();
P3 = 0XF0; P44 = 1; P42 = 1;
key_temp |= get();
if(key_temp != 0xff && !key_buf)
{
key_buf = key_temp;
}
}
else if(key_temp == 0xff && key_buf)
{
Delay5ms();
P3 = 0X0F; P44 = 0; P42 = 0;
key_temp = get();
P3 = 0XF0; P44 = 1; P42 = 1;
key_temp |= get();
if(key_temp == 0xff && key_buf)
{
switch(key_buf) // 这里要特别注意是key_buf,不要粗心写成了key_temp
{
// case 0x7e: disbuf[1] = 7; disbuf[2] = 10; disbuf[3] = 10; break;
// case 0x7d: disbuf[1] = 6; disbuf[2] = 10; disbuf[3] = 10; break;
case 0x7b: // s5
mode = !mode;
break;
case 0x77: // s6
switch(interface)
{
case TEMP_INTERFACE:
temperature_para_temp = temperature_para;
interface = SETTING_INTERFACE;
break;
case SETTING_INTERFACE:
temperature_para = temperature_para_temp;
interface = DAC_INTERFACE;
break;
case DAC_INTERFACE:
interface = TEMP_INTERFACE;
break;
}
break;
// case 0xbe: disbuf[1] = 1; disbuf[2] = 1; disbuf[3] = 10; break;
// case 0xbd: disbuf[1] = 1; disbuf[2] = 0; disbuf[3] = 10; break;
case 0xbb: // s9
temperature_para_temp++;
break;
case 0xb7: // s8
temperature_para_temp--;
break;
// case 0xde: disbuf[1] = 1; disbuf[2] = 5; disbuf[3] = 10; break;
// case 0xdd: disbuf[1] = 1; disbuf[2] = 4; disbuf[3] = 10; break;
// case 0xdb: disbuf[1] = 1; disbuf[2] = 3; disbuf[3] = 10; break;
// case 0xd7: disbuf[1] = 1; disbuf[2] = 2; disbuf[3] = 10; break;
//
// case 0xee: disbuf[1] = 1; disbuf[2] = 9; disbuf[3] = 10; break;
// case 0xed: disbuf[1] = 1; disbuf[2] = 8; disbuf[3] = 10; break;
// case 0xeb: disbuf[1] = 1; disbuf[2] = 7; disbuf[3] = 10; break;
// case 0xe7: disbuf[1] = 1; disbuf[2] = 6; disbuf[3] = 10; break;
}
key_buf = 0;
}
}
}
void smg_proc(void)
{
set_port(0xc0, 0x01 << smg_cnt);
if((interface == TEMP_INTERFACE && smg_cnt == 5) || (interface == DAC_INTERFACE && smg_cnt == 5))
set_port(0xe0, TAB[disbuf[smg_cnt + 1]] & 0x7F);
else
set_port(0xe0, TAB[disbuf[smg_cnt + 1]]);
if(++smg_cnt >= 8) smg_cnt = 0;
if(++sec_tick == 1000)
{
sec_tick = 0;
(sec_cnt != 59)?(sec_cnt++):(sec_cnt = 0);
}
}
void dac_proc(void)
{
if(mode == 0)
{
if(temperature < temperature_para)
write_pcf8591(0);
else
write_pcf8591(255);
}
else
{
if(temperature < 20)
write_pcf8591(0);
else if(temperature > 40)
write_pcf8591(255);
else
write_pcf8591((6.0 / 40 * temperature - 2) / 5.0 * 255);
}
}
void led_proc(void)
{
u8 led_state = 0xff;
if(mode == 0)
led_state &= 0xFE;
if(interface == TEMP_INTERFACE)
led_state &= 0xFD;
else if(interface == SETTING_INTERFACE)
led_state &= 0xFB;
else if(interface == DAC_INTERFACE)
led_state &= 0xF7;
set_port(0x80,led_state);
}
/********************* Timer2中断函数************************/
void timer2_int (void) interrupt 12
{
smg_proc();
led_proc();
}
void main(void)
{
allinit(); // 上电初始化
Timer2Init(); // 定时器2初始化
IE2 |= 0x04; // 开定时器2中断
EA = 1; // 开启总中断
while(1)
{
temperature = read_temperature();
dac_proc();
display();
KBD();
}
}
转载:https://blog.csdn.net/qq_43715171/article/details/116534291
查看评论