一、赛题分析
对于本届赛题,涉及模块不多,相对简短。主要难度集中在USART、E2PROM上。对于串口接收数据,当数据接收到时,要及时对接收数组清0,否则会影响下次串口接收。对于E2PROM的存储功能,只需要在串口接收完毕之后写入一次,再在while(1)之前读取一次即可掉电保护。
二、程序设计
IIC、LED、KEY、USART等初始化均可在上一篇文章找到:
蓝桥杯嵌入式——第四届省赛“双路输出控制器”旧板标准库_对愁眠后霜满天的博客-CSDN博客
或在文章最后附上的链接处下载工程。
1、ADC初始化
#ifndef __ADC_H
#define __ADC_H
#include "stm32f10x.h"
#include "stdio.h"
void ADC_INIT(void);
float Read_ADC(void);
#endif
#include "adc.h"
#include "delay.h"
#include "stm32f10x_adc.h"
void ADC_INIT(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
ADC_InitTypeDef ADC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
//PB0-ADC channel 8
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_Init(GPIOB, &GPIO_InitStructure);
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
ADC_InitStructure.ADC_ScanConvMode = DISABLE;
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; //µ¥´Îת»»
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_NbrOfChannel = 1;
ADC_Init(ADC1, &ADC_InitStructure);
ADC_RegularChannelConfig(ADC1, ADC_Channel_8, 1, ADC_SampleTime_13Cycles5);
ADC_Cmd(ADC1, ENABLE);
ADC_ResetCalibration(ADC1);
/* Check the end of ADC1 reset calibration register */
while(ADC_GetResetCalibrationStatus(ADC1));
ADC_StartCalibration(ADC1);
/* Check the end of ADC1 calibration */
while(ADC_GetCalibrationStatus(ADC1));
}
float Read_ADC(void)
{
float ADC_VALUE;
ADC_SoftwareStartConvCmd(ADC1,ENABLE);
Delay_Ms(5);
ADC_VALUE = ADC_GetConversionValue(ADC1)*3.30/0xfff;
return ADC_VALUE;
}
在stm32f10x_it.c中用系统滴答定时器延时ADC采集,做到200ms更新一次数据。只需要在主函数中将ADC_Flag置0,读取Read_ADC即可。
extern u32 TimingDelay;
extern u8 ADC_Flag;
u8 Ms = 0;
void SysTick_Handler(void)
{
TimingDelay--;
if(++Ms == 200){
Ms = 0;
ADC_Flag = 1;
}
}
2、USART部分改动
由输入格式“k0.1\n”即可知道,当USART_RXBUF[5] == 'n'时可判断串口接收完毕。当k得到幅值时,USART_RXBUF要清0,否则多次发送则会出错。在此串口接收到的数据为字符形式,减去48即可得到对应数字。
void usart_port(void)
{
if(RXOVER == 1)
{
RXOVER = 0;
RXCUNT = 0;
k = USART_RXBUF[3] - 48;
i2c_write(0x60,(u8)k);Delay_Ms(10); //i2c写入
USART_SendString(USART2,(u8*)"ok\\n\r\n"); //返回ok
memset(USART_RXBUF,0,sizeof(USART_RXBUF)); //USART_RXBUF清0
}
if(_h == a.hou&&_m == a.min&&_s == a.sec&&send_flag == 0)//报警功能实现处
{
send_flag = 1;
memset(string,0,sizeof(string));
sprintf((char*)string,"%.2f+%.1f+%02d%02d%02d\\n\r\n",adc_temp,k/10,_h,_m,_s);
USART_SendString(USART2,string);
}
}
3.main.c主程序
程序编写浅显易懂,不做过多分析。个别处以在代码中做出注释。
#include "stm32f10x.h"
#include "lcd.h"
#include "led.h"
#include "key.h"
#include "delay.h"
#include "rtc.h"
#include "adc.h"
#include "usart.h"
#include "timer.h"
#include "i2c.h"
#include "stdio.h"
#include "string.h"
struct alarm_time{u8 hou,min,sec;}a={0,0,0};
enum LED_STAT{OFF,ON};
enum SHOW_STAT{MAIN,SETTING};
u8 show_flag = MAIN,off_on_flag = OFF;
u8 key_flag = 0,ADC_Flag,led_flag = 0,select_flag = 0,send_flag = 0;
u8 string[20];
u8 temp1 = 6,temp2 = 7;
float adc_temp,k = 1;
void key_in(void);
void show_lcd(void);
void highlight_char(u8 Line, u8 *ptr);
void usart_port(void);
void led_shine(void);
//Main Body
int main(void)
{
STM3210B_LCD_Init();
LCD_Clear(Black);
LCD_SetBackColor(Black);
LCD_SetTextColor(White);
SysTick_Config(SystemCoreClock/1000);
TIM4_Init();
LED_Init();
KEY_Init();
ADC_INIT();
i2c_init();
USART2_Init(9600);
RTC_Init(23,59,55);
k = i2c_read(0x60);
if(k>10||k==0)k=1;
while(1)
{
update_time();
show_lcd();
key_in();
usart_port();
led_shine();
}
}
void key_in(void)
{
key_flag = key_scan();
if(key_flag == 1)
{
off_on_flag =! off_on_flag;
}
if(key_flag == 2)
{
show_flag =! show_flag;
select_flag = 0;
send_flag = 0;
temp1 = 6;temp2 = 7;
LCD_Clear(Black);
}
if(key_flag == 3 && show_flag == SETTING)//改变高光系数
{
select_flag = (select_flag + 1) % 3;
if(select_flag == 0){temp1 = 6;temp2 = 7;}
if(select_flag == 1){temp1 = 9;temp2 = 10;}
if(select_flag == 2){temp1 = 12;temp2 = 13;}
}
if(key_flag == 4 && show_flag == SETTING)//改变定时上报时间
{
if(select_flag == 0)a.hou = (a.hou + 1) % 24;
if(select_flag == 1)a.min = (a.min + 1) % 60;
if(select_flag == 2)a.sec = (a.sec + 1) % 60;
}
}
void show_lcd(void)
{
if(show_flag == MAIN)
{
if(ADC_Flag)
{
ADC_Flag = 0;
adc_temp = Read_ADC();
memset(string,0,sizeof(string));
sprintf((char*)string," V1:%.2fV ",adc_temp);
LCD_DisplayStringLine(Line1,string);
}
memset(string,0,sizeof(string));
sprintf((char*)string," k:%.1f ",k/10);
LCD_DisplayStringLine(Line3,string);
switch(off_on_flag)
{
case OFF: LCD_DisplayStringLine(Line5,(u8*)" LED:OFF ");break;
case ON : LCD_DisplayStringLine(Line5,(u8*)" LED:ON ");break;
default : break;
}
LCD_DisplayStringLine(Line7,(u8*)time_str);
LCD_DisplayStringLine(Line9,(u8*)" 1");
}
if(show_flag == SETTING)
{
LCD_DisplayStringLine(Line1,(u8*)" Setting ");
memset(string,0,sizeof(string));
sprintf((char*)string," %02d-%02d-%02d ",a.hou,a.min,a.sec);
highlight_char(Line4,string);
LCD_DisplayStringLine(Line9,(u8*)" 2");
}
}
/*
字体高光函数,只需要改变temp1、temp2即可改变高光位置。
*/
void highlight_char(u8 Line, u8 *ptr)
{
u32 i = 0;
u16 refcolumn = 319;
while ((*ptr != 0) && (i < 20))
{
if(i == temp1 || i == temp2)
{
LCD_SetTextColor(Yellow);
}
LCD_DisplayChar(Line, refcolumn, *ptr);
LCD_SetTextColor(White);
refcolumn -= 16;
ptr++;
i++;
}
}
void usart_port(void)
{
if(RXOVER == 1)
{
RXOVER = 0;
RXCUNT = 0;
k = USART_RXBUF[3] - 48;
i2c_write(0x60,(u8)k);Delay_Ms(10); //i2c写入
USART_SendString(USART2,(u8*)"ok\\n\r\n"); //返回ok
memset(USART_RXBUF,0,sizeof(USART_RXBUF)); //USART_RXBUF清0
}
if(_h == a.hou&&_m == a.min&&_s == a.sec&&send_flag == 0)//报警功能实现处
{
send_flag = 1;
memset(string,0,sizeof(string));
sprintf((char*)string,"%.2f+%.1f+%02d%02d%02d\\n\r\n",adc_temp,k/10,_h,_m,_s);
USART_SendString(USART2,string);
}
}
//报警函数
void led_shine(void)
{
if(off_on_flag == OFF&&show_flag == MAIN)
{
if(adc_temp>3.3*k/10)LED_Control(LED1,led_flag);
else LED_Control(LED1,0);
}
else LED_Control(LED1,0);
}
void TIM4_IRQHandler(void)
{
static u16 led_cnt = 0;
if(TIM_GetITStatus(TIM4,TIM_IT_Update) != RESET)
{
TIM_ClearITPendingBit(TIM4, TIM_IT_Update);
if(++led_cnt>=200)
{
led_cnt = 0;
led_flag =! led_flag;
}
}
}
三、附上工程
链接:https://pan.baidu.com/s/1Jw4MTK2QQ26_SDN8qNiBNw
提取码:kcgi
有不对的地方,请多指教...