蓝桥杯嵌入式第十三届省赛第二场
1.注意eep存浮点数的方式和不要忘记IIC初始化2.不要打成中文下的问号。
·
目录
一.题目要求
1.功能要求

2.界面显示


3.按键


4.EEP存储
注意:可以不在CubeMX配置PB6和PB7为ouput (配置的话可以不调用),但一定不要忘记在main中调用IIC初始化函数。此外要注意EEP不能直接存浮点数

5.串口发送接收
注意:不要用成中文的问号
6.LED和PWM,及初始化

二.main中
#include "user.h"
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_USART1_UART_Init();
MX_TIM2_Init();
MX_TIM3_Init();
LCD_Init(); //一定要加,不然LCD不能用
I2CInit(); //一定要加,不然IIC不能用
LCD_Clear(Black);
LCD_SetBackColor(Black);
LCD_SetTextColor(White);
XY_Init(); //商品信息初始化
HAL_UART_Receive_IT(&huart1,&rx_data,1); //串口接收中断
HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_2); //输出PWM
HAL_TIM_Base_Start_IT(&htim3); //定时
while (1)
{
key_proc();
lcd_proc();
uart_rx_proc();
led_proc();
pwm_proc();
}
}
三.user.c中
#include "user.h"
extern UART_HandleTypeDef huart1;
extern TIM_HandleTypeDef htim2; //生成PWM,CCR2
extern TIM_HandleTypeDef htim3; //定时
void AT24C02_Write(uint8_t address,uint8_t data)
{
I2CStart();
I2CSendByte(0xa0);
I2CWaitAck();
I2CSendByte(address);
I2CWaitAck();
I2CSendByte(data);
I2CWaitAck();
I2CStop();
}
uint8_t AT24C02_Read(uint8_t address)
{
uint8_t data;
I2CStart();
I2CSendByte(0xa0);
I2CWaitAck();
I2CSendByte(address);
I2CWaitAck();
I2CStart();
I2CSendByte(0xa1);
I2CWaitAck();
data = I2CReceiveByte();
I2CSendNotAck();
I2CStop();
return data;
}
uint8_t key_value,key_down,key_up,key_old = 0;
void key_scan(void)
{
if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0) == RESET)
key_value = 1;
else if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1) == RESET)
key_value = 2;
else if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_2) == RESET)
key_value = 3;
else if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0) == RESET)
key_value = 4;
else key_value = 0;
key_down = key_value & (key_value ^ key_old);
key_up = ~key_value & (key_value ^ key_old);
key_old = key_value;
}
uint8_t X_Stock = 10,Y_Stock = 10; //库存数量
uint8_t X_Shop = 0,Y_Shop = 0; //购买数量
double X_Price = 1.0,Y_Price = 1.0; //商品价格
uint8_t page_index = 1; //页面
struct Shop Shop_info = {0}; //购买信息结构体变量
uint8_t led_flag[2] = {0,0}; //两个灯的标志位,0灭1亮
uint8_t pwm_mode = 0; //pwm调占空比,0输出5%,1输出30%
uint32_t key_tick = 0;
void key_proc(void)
{
if(uwTick - key_tick < 10)
return;
key_tick = uwTick;
key_scan();
if(key_down == 1) //页面切换
{
page_index ++;
LCD_Clear(Black);
if(page_index == 4)page_index = 1;
}
else if(key_down == 2) //X
{
switch(page_index)
{
case 1:
{
if(X_Shop < X_Stock)
{
X_Shop ++;
if(X_Shop == X_Stock)X_Shop = X_Stock;
}
else if(X_Shop >= X_Stock)X_Shop = 0;
}break;
case 2:
{
if(X_Price < 2.0)X_Price += 0.1;
else if(X_Price >= 2.0)X_Price = 1.0;
AT24C02_Write(0x02,(uint8_t)(X_Price * 10));
HAL_Delay(5);
}break;
case 3:
{
X_Stock ++;
led_flag[1] = 0;
AT24C02_Write(0x00,X_Stock);
HAL_Delay(5);
}break;
}
}
else if(key_down == 3) //Y
{
switch(page_index)
{
case 1:
{
if(Y_Shop < Y_Stock)
{
Y_Shop ++;
if(Y_Shop == Y_Stock)Y_Shop = Y_Stock;
}
else if(Y_Shop >= Y_Stock)Y_Shop = 0;
}break;
case 2:
{
if(Y_Price < 2.0)Y_Price += 0.1;
else if(Y_Price >= 2.0)Y_Price = 1.0;
AT24C02_Write(0x03,(uint8_t)(Y_Price * 10));
HAL_Delay(5);
}break;
case 3:
{
Y_Stock ++;
led_flag[1] = 0; //有库存
AT24C02_Write(0x01,Y_Stock);
HAL_Delay(5);
}break;
}
}
//按下,有购买的商品(库存肯定有),在页面一
else if(key_down == 4 && (X_Shop > 0 || Y_Shop > 0) && page_index == 1)
{
//确认购买的信息
Shop_info.Shop_Quantity[0]= X_Shop;
Shop_info.Shop_Quantity[1]= Y_Shop;
Shop_info.Shop_Price[0] = X_Price;
Shop_info.Shop_Price[1] = Y_Price;
//算总价格
Shop_info.All_Price = Shop_info.Shop_Quantity[0] * Shop_info.Shop_Price[0] +
Shop_info.Shop_Quantity[1] * Shop_info.Shop_Price[1];
//打印购买信息
printf("X:%d,Y:%d,Z:%.1lf",Shop_info.Shop_Quantity[0],Shop_info.Shop_Quantity[1],Shop_info.All_Price);
//库存有变
X_Stock -= X_Shop;
Y_Stock -= Y_Shop;
AT24C02_Write(0x00,X_Stock);
HAL_Delay(5);
AT24C02_Write(0x01,Y_Stock);
HAL_Delay(5);
led_flag[0] = 1; //LD1亮
pwm_mode = 1; //PWM输出占空比30%
X_Shop = Y_Shop = 0; //清除购买页面信息
}
else if(X_Stock == 0 && Y_Stock == 0) //没有库存
{
led_flag[1] = 1;
}
}
void XY_Init(void)
{
//地址随便读一个就行,数据随给一个,只要不超过255
if(AT24C02_Read(123) != 125) //第一次烧录或复位,进行变量初始化
{
AT24C02_Write(123,125);
X_Stock = 10;
Y_Stock = 10;
X_Price = 1.0;
Y_Price = 1.0;
HAL_Delay(5);
AT24C02_Write(0x00,X_Stock);
HAL_Delay(5);
AT24C02_Write(0x01,Y_Stock);
HAL_Delay(5);
AT24C02_Write(0x02,(uint8_t)(X_Price * 10));
HAL_Delay(5);
AT24C02_Write(0x03,(uint8_t)(Y_Price * 10));
HAL_Delay(5);
}
else //不是第一次烧录或复位,读取上一次的数据
{
X_Stock = AT24C02_Read(0x00);
HAL_Delay(5);
Y_Stock = AT24C02_Read(0x01);
HAL_Delay(5);
X_Price = AT24C02_Read(0x02)/10.0;
HAL_Delay(5);
Y_Price = AT24C02_Read(0x03)/10.0;
HAL_Delay(5);
}
}
uint16_t time_ms = 0;
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if(htim -> Instance == TIM3)
{
if(led_flag[0] == 1)time_ms ++;
if(time_ms == 5000) //5秒定时
{
time_ms = 0;
pwm_mode = 0;
led_flag[0] = 0;
}
}
}
void led_disp(u8 ucled)
{
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_All,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOC,ucled << 8,GPIO_PIN_RESET);
HAL_Delay(2); //一定要加,不然闪烁亮度低
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);
}
uint32_t led_tick = 0;
uint8_t lednum = 0;
void led_proc(void)
{
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_All,GPIO_PIN_SET);
if(led_flag[0] == 1) //LD1
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_8,GPIO_PIN_RESET);
else
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_8,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);
if(uwTick - led_tick < 100)
return;
led_tick = uwTick;
if(led_flag[1] == 1)lednum |= 2; //LD2
else if(led_flag[1] == 0)lednum &= ~2;
led_disp(lednum);
}
uint32_t pwm_tick = 0;
void pwm_proc(void)
{
if(uwTick - pwm_tick < 100)
return;
pwm_tick = uwTick;
if(pwm_mode == 1) //30%
TIM2 -> CCR2 = 150;
else //5%
TIM2 -> CCR2 = 25;
}
char buf[30];
uint32_t lcd_tick = 0;
void lcd_proc(void)
{
if(uwTick - lcd_tick < 150)
return;
lcd_tick = uwTick;
if(page_index == 1)
{
LCD_DisplayStringLine(Line1,(u8 *)" SHOP ");
sprintf(buf," X:%d ",X_Shop);
LCD_DisplayStringLine(Line3,(u8 *)buf);
sprintf(buf," Y:%d ",Y_Shop);
LCD_DisplayStringLine(Line4,(u8 *)buf);
}
else if(page_index == 2)
{
LCD_DisplayStringLine(Line1,(u8 *)" PRICE ");
sprintf(buf," X:%.1lf ",X_Price);
LCD_DisplayStringLine(Line3,(u8 *)buf);
sprintf(buf," Y:%.1lf ",Y_Price);
LCD_DisplayStringLine(Line4,(u8 *)buf);
}
else
{
LCD_DisplayStringLine(Line1,(u8 *)" REP ");
sprintf(buf," X:%d ",X_Stock);
LCD_DisplayStringLine(Line3,(u8 *)buf);
sprintf(buf," Y:%d ",Y_Stock);
LCD_DisplayStringLine(Line4,(u8 *)buf);
}
}
int fputc(int ch,FILE *p)
{
uint8_t c = (uint8_t)ch;
HAL_UART_Transmit(&huart1,&c,1,50);
return ch;
}
#define RX_BUF_SIZE 64
#define RX_TIMEOUT 100
uint32_t last_rx_tick = 0; //最后接收数据的时刻
uint8_t rx_pointer = 0,rx_data,rx_buf[RX_BUF_SIZE];
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if(rx_pointer < RX_BUF_SIZE - 1)
{
rx_buf[rx_pointer ++] = rx_data;
last_rx_tick = uwTick; //更新最后接收数据的时刻
}
HAL_UART_Receive_IT(&huart1,&rx_data,1);
}
void uart_rx_proc(void)
{
//超时处理
if((uwTick - last_rx_tick > RX_TIMEOUT) && rx_pointer > 0)
{
if(rx_pointer == 1)
{
if(rx_buf[0] == '?') //注意不要用到中文的问号?
{
printf("X:%.1lf,Y:%.1lf",X_Price,Y_Price);
}
}
rx_pointer = 0;
memset(rx_buf,0,sizeof(rx_buf));
}
}
四.user.h中
#ifndef __USER_H
#define __USER_H
#include "main.h"
#include "stdio.h"
#include "string.h"
#include "i2c_hal.h"
void key_proc(void);
void lcd_proc(void);
void AT24C02_Write(uint8_t address,uint8_t data);
uint8_t AT24C02_Read(uint8_t address);
void XY_Init(void);
int fputc(int ch,FILE *p);
void uart_rx_proc(void);
void led_proc(void);
void pwm_proc(void);
struct Shop //购买信息结构体
{
uint8_t Shop_Quantity[2];
double Shop_Price[2];
double All_Price;
};
extern uint8_t rx_data;
#endif
五.总结
1.注意eep存浮点数的方式和不要忘记IIC初始化
2.不要打成中文下的问号
openvela 操作系统专为 AIoT 领域量身定制,以轻量化、标准兼容、安全性和高度可扩展性为核心特点。openvela 以其卓越的技术优势,已成为众多物联网设备和 AI 硬件的技术首选,涵盖了智能手表、运动手环、智能音箱、耳机、智能家居设备以及机器人等多个领域。
更多推荐




所有评论(0)