蓝桥杯嵌入式十三届第二场

蓝桥杯嵌入式十三届第二场


前言:使用新板子stm32G431,由于笨人大概属于偏业余,全部使用HAL库函数实现,可读性应该蛮高的,最后写完没认真检查,如有问题欢迎指正。

所有变量、结构体以及功能实现函数

/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "tim.h"
#include "usart.h"
#include "gpio.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "stdio.h"
#include "lcd.h"
#include "i2c.h"
#include "stdbool.h"
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
typedef struct keys
{
	uint8_t step;			//按键的步骤
	bool key_state;			//按键的状态
	bool single_flag;		//按键单击标志
}KEY;
KEY key[4]={0,0,0};
/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
#define LED1 GPIO_PIN_8
#define LED2 GPIO_PIN_9
#define LED3 GPIO_PIN_10
#define LED4 GPIO_PIN_11
#define LED5 GPIO_PIN_12
#define LED6 GPIO_PIN_13
#define LED7 GPIO_PIN_14
#define LED8 GPIO_PIN_15
/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */
char text[30];
int x_purchase=0;			//x购买数量
int x_count=10;				//x库存
double x_price=1.0;			//x单价
int y_purchase=0;
int y_count=10;
double y_price=1.0;
uint8_t view_flag=0;	//显示界面标志
uint8_t rx[20];
uint8_t data;
__IO uint32_t LEDuwTick1=0xffffff,LEDuwTick2,PWMuwTick=0xffffff;

uint8_t eeprom_read(uint8_t addr);
void eeprom_write(uint8_t addr,uint8_t data);
/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */
//重写printf函数
int fputc(int c,FILE* Stream)
{
	HAL_UART_Transmit(&huart1,(unsigned char *)&c,1,1000);
	return 1;
}
//关闭所有LED灯
void LED_OFF(void)
{
	HAL_GPIO_WritePin(GPIOC,GPIO_PIN_All,GPIO_PIN_SET);
	HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);
	HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);
}
//控制LED开关
void LED_Control(uint16_t LED,uint8_t LED_Status)
{
	if(LED_Status==0)
	{
		HAL_GPIO_WritePin(GPIOC,LED,GPIO_PIN_SET);
		HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);
		HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);
	}		
	else
	{
		HAL_GPIO_WritePin(GPIOC,LED,GPIO_PIN_RESET);
		HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);
		HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);
	}
}


//翻转LED
void LED_Toggle(uint16_t LED)
{
	HAL_GPIO_TogglePin(GPIOC,LED);
	HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);
	HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);
}
void LED_proc()
{
	if(uwTick-LEDuwTick1<5000)
		LED_Control(LED1,1);
	else 
		LED_Control(LED1,0);
	
	if(x_count==0&&y_count==0)
	{
		if(uwTick-LEDuwTick2>100)
		{
			LEDuwTick2=uwTick;
			LED_Toggle(LED2);
		}
	}
	else LED_Control(LED2,0);
}
//显示屏清除
void view_clear()
{
	LCD_Clear(Black);
	LCD_SetBackColor(Black);
	LCD_SetTextColor(White);
}
//商品购买界面
void view_SHOP()
{
	sprintf(text,"        SHOP");
	LCD_DisplayStringLine(Line2,(uint8_t *)text);
	sprintf(text,"     X:%d",x_purchase);
	LCD_DisplayStringLine(Line4,(uint8_t *)text);
	sprintf(text,"     Y:%d",y_purchase);
	LCD_DisplayStringLine(Line5,(uint8_t *)text);
}
//商品价格界面
void view_PRICE()
{
	sprintf(text,"        PRICE");
	LCD_DisplayStringLine(Line2,(uint8_t *)text);
	sprintf(text,"     X:%.1f",x_price);
	LCD_DisplayStringLine(Line4,(uint8_t *)text);
	sprintf(text,"     Y:%.1f",y_price);
	LCD_DisplayStringLine(Line5,(uint8_t *)text);
}
//库存信息界面
void view_REP()
{
	sprintf(text,"        PER");
	LCD_DisplayStringLine(Line2,(uint8_t *)text);
	sprintf(text,"     X:%d",x_count);
	LCD_DisplayStringLine(Line4,(uint8_t *)text);
	sprintf(text,"     Y:%d",y_count);
	LCD_DisplayStringLine(Line5,(uint8_t *)text);
}
//重写TIM3的中断回调函数
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
	if(htim->Instance==TIM3)
	{
		//读取每个按键当前的状态
		key[0].key_state=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0);
		key[1].key_state=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1);
		key[2].key_state=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_2);
		key[3].key_state=HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0);
		
		for(int i=0;i<4;i++)
		{
			switch(key[i].step)
			{
				case 0:
					//如果按键现在为低电平,则进入下一步继续判断(按键消抖)
					if(key[i].key_state==0)
						key[i].step=1;
					break;
				case 1:
					//如果按键现在仍为低电平,则判断按键被按键,否则视为抖动,返回上一步
					if(key[i].key_state==0)
					{
						key[i].single_flag=1;
						key[i].step=2;
					}
					else	key[i].step=0;
					break;
				case 2:
					//按键被松开,返回第一步
					if(key[i].key_state==1)
						key[i].step=0;
					break;
			}
		}
	}
}
void KEY_proc()
{
		if(key[0].single_flag==1)
		{
			if(view_flag==0)
			{
				x_purchase=0;
				y_purchase=0;
			}
			view_flag=(view_flag+1)%3;
			view_clear();
			switch(view_flag)
			{
				case 0:
					view_SHOP();
					break;
				case 1:
					view_PRICE();
					break;
				case 2:
					view_REP();
					break;
			}
			key[0].single_flag=0;
		}
		if(key[1].single_flag==1)
		{
			switch(view_flag)
			{
				case 0:
					if(x_purchase==x_count)
						x_purchase=0;
					else
						x_purchase++;
					view_SHOP();
					break;
				case 1:
					if(x_price>=2.0)
						x_price=1.0;
					else
						x_price+=0.1;
					view_PRICE();
					eeprom_write(0x02,x_price*10.0); //注意此处若*10小数点后一位会被吞掉
					break;
				case 2:
					x_count++;
					view_REP();
					eeprom_write(0x00,x_count);
					break;
			}
			key[1].single_flag=0;
		}
		if(key[2].single_flag==1)
		{
			switch(view_flag)
			{
				case 0:
					if(y_purchase==y_count)
						y_purchase=0;
					else 
						y_purchase++;
					view_SHOP();
					break;
				case 1:
					if(y_price>=2.0)
						y_price=1.0;
					else
						y_price+=0.1;
					view_PRICE();
					eeprom_write(0x03,y_price*10.0);
					break;
				case 2:
					y_count++;
					view_REP();
					eeprom_write(0x01,y_count);
					break;
			}
			key[2].single_flag=0;
		}
		if(key[3].single_flag==1)
		{
			if(view_flag==0)
			{
				x_count-=x_purchase;
				y_count-=y_purchase;
				printf("X:%d,Y:%d,Z=%.1f\n",x_purchase,y_purchase,(x_purchase*x_price)+(y_price*y_price));
				x_purchase=0;
				y_purchase=0;	
			
				LEDuwTick1=uwTick;	//计时触发
				PWMuwTick=uwTick;
			}
			view_clear();
			view_SHOP();
			
			eeprom_write(0x00,x_count);
			HAL_Delay(10);
			
			eeprom_write(0x01,y_count);
			HAL_Delay(10);
			
			key[3].single_flag=0;
		}
}
//uart_receive的回调函数
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	if(huart->Instance==USART1)
	{
		if(rx[0]=='?')
			printf("X:%.1f,Y:%.1f\n",x_price,y_price);
	}
	HAL_UART_Receive_IT(&huart1,rx,1);	//注意此处需要再开启接收中断,否则无法继续接收
}
void PWM_proc()
{
	if(uwTick-PWMuwTick<5000)
	{ 
		__HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_2,30);	//调整占空比为30% 前提:htim2.Init.Period = 99;
	}
	else
	{
		__HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_2,5);	//调整占空比为5%
	}
}
void ee_proc()
{
	data=eeprom_read(0x08);	//判断是否为第一次上电
	if(data!=0x99) 					//如果为第一次上电 将数据写入eeprom
	{
		data=0x99;
		eeprom_write(0x08,data);
		
		eeprom_write(0x00,x_count);
		eeprom_write(0x01,y_count);
		eeprom_write(0x02,x_price*10.0);
		eeprom_write(0x03,y_price*10.0);
	}
	else							//如果不是第一次上电 从eeprom读取数据
	{
		x_count=eeprom_read(0);
		y_count=eeprom_read(1);
		x_price=eeprom_read(2)/10.0;
		y_price=eeprom_read(3)/10.0;
	}
}
/* USER CODE END PFP */

main函数

int main(void)
{
  /* USER CODE BEGIN 1 */
  /* USER CODE END 1 */
  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */
	
  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_TIM3_Init();
  MX_USART1_UART_Init();
  MX_TIM2_Init();
  /* USER CODE BEGIN 2 */
	I2CInit();
	LCD_Init();	//初始化LCD
	view_clear();//清屏
	view_SHOP(); //上电默认处于商品购买界面
	LED_OFF();	//初始化关闭所有LED灯
	HAL_TIM_Base_Start_IT(&htim3);	//打开TIM3 用于按键
	HAL_UART_Receive_IT(&huart1,rx,1);
	HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_2);	//开启PWM
	ee_proc();	//eeprom操作
	
  /* USER CODE END 2 */
  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
		LED_proc();		
		KEY_proc();
		PWM_proc();
  }
  /* USER CODE END 3 */
}

eeprom的读写函数

uint8_t eeprom_read(uint8_t addr)
{
	uint8_t data;
	
	I2CStart();
	I2CSendByte(0xa0);
	I2CWaitAck();
	I2CSendByte(addr);
	I2CWaitAck();
	I2CStop();
	
	I2CStart();
	I2CSendByte(0xa1);
	I2CWaitAck();
	data=I2CReceiveByte();
	I2CSendNotAck();
	I2CStop();
	
	return data;
	
}
void eeprom_write(uint8_t addr,uint8_t data)
{
	I2CStart();
	I2CSendByte(0xa0);
	I2CWaitAck();
	I2CSendByte(addr);
	I2CWaitAck();
	
	I2CSendByte(data);
	I2CWaitAck();
	I2CStop();
	
	HAL_Delay(10);
}

完整工程链接!!!

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值