温馨提示:
真题演练分为模拟篇和研究篇。本专栏的主要作用是记录我的备赛过程,我打算先自己做一遍,把遇到的问题和不同之处记录到演练篇,然后再返回来仔细研究一下,找到最佳的解题方法记录到研究篇。题目在:https://pan.quark.cn/s/fc121e80dbff
问题记录
演练用时:4小时10分
完成度:“设备重新上电,能够从 E2PROM 相应地址中载入商品库存数量和价格。”功能未实现,原因是不会将char类型数据转换为其他类型数据。
解题过程中遇到的问题:
- LED控制:由于LCD的影响,必须要在点亮LED灯前关闭其他LED灯。之前使用驱动文件的方法,写了两个函数,是为了提高灵活性,如此看来,这样做是没有必要的。既然如此不如在驱动函数中就直接关闭其他LED灯。代码如下:
void LED_switch(uint16_t GPIO_Pin,GPIO_PinState PinState) { HAL_GPIO_WritePin(LED_LE_GPIO_Port,LED_LE_Pin,GPIO_PIN_SET); HAL_GPIO_WritePin(GPIOC,LED1_Pin|LED2_Pin|LED3_Pin|LED4_Pin|LED5_Pin|LED6_Pin|LED7_Pin|LED8_Pin,GPIO_PIN_SET); HAL_GPIO_WritePin(GPIOC,GPIO_Pin,PinState); HAL_GPIO_WritePin(LED_LE_GPIO_Port,LED_LE_Pin,GPIO_PIN_RESET); }
- 串口
- 接收缓冲区的大小需要用sizeof()来确定,一般题目设置为定值即可。
- 发送一般需要加换行符,所以发送缓冲区的大小需要用strlen()来确定。
- 发送缓冲区要设置为一个有足够且大小的确定的数组。
- 串口接收函数要在处理前延时50ms。
未解决的问题:
题目要求初始化,又要求复位后可以从存储芯片中读取价格和库存,但是写入的是char类型的数据,所以数据类型转化是一个问题,之前没有考虑过读取各种数据的方法。需要专门学习一下。
解题记录
草稿:
功能代码:
main.c
/* USER CODE BEGIN PV */
uint8_t B1_key=1;
uint8_t LD1_f=0;
uint8_t LD2_f=0;
uint32_t SHOP_X=0;
float PRICE_X=1.0;
uint32_t REP_X=10;
float oldPRICE_X=1.0;
uint32_t oldREP_X=10;
uint32_t SHOP_Y=0;
float PRICE_Y=1.0;
uint32_t REP_Y=10;
float oldPRICE_Y=1.0;
uint32_t oldREP_Y=10;
unsigned char REP_Xbuf[10];
unsigned char REP_Ybuf[10];
unsigned char PRICE_Xbuf[10];
unsigned char PRICE_Ybuf[10];
char LCD_str[20];
uint8_t rxBuf[1];
char txBuf[40];
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
//LED驱动
void LED_switch(uint16_t GPIO_Pin,GPIO_PinState PinState)
{
HAL_GPIO_WritePin(GPIOC,GPIO_Pin,PinState);
HAL_GPIO_WritePin(LED_LE_GPIO_Port,LED_LE_Pin,GPIO_PIN_SET);
HAL_GPIO_WritePin(LED_LE_GPIO_Port,LED_LE_Pin,GPIO_PIN_RESET);
}
//存入数据
void rem()
{
sprintf(REP_Xbuf,"%d",REP_X);
sprintf(REP_Ybuf,"%d",REP_Y);
sprintf(PRICE_Xbuf,"%.1f",PRICE_X);
sprintf(PRICE_Ybuf,"%.1f",PRICE_Y);
iic_24c02_write(REP_Xbuf,0,sizeof(REP_Xbuf));
iic_24c02_write(REP_Ybuf,1,sizeof(REP_Ybuf));
iic_24c02_write(PRICE_Xbuf,2,sizeof(PRICE_Xbuf));
iic_24c02_write(PRICE_Ybuf,3,sizeof(PRICE_Ybuf));
}
//改变价格
void changePRICE()
{
if(oldPRICE_X!=PRICE_X||oldPRICE_Y!=PRICE_Y)
{
oldPRICE_X=PRICE_X;
oldPRICE_Y=PRICE_Y;
rem();
}
}
//LD2闪烁
void LD2_fun()
{
if(REP_X==0&&REP_Y==0&&LD2_f==0)
{
HAL_TIM_Base_Start_IT(&htim7);
LD2_f=1;
}
else if(LD2_f==1)
{
HAL_TIM_Base_Stop_IT(&htim7);
LD2_f=0;
}
}
//LED控制,将LED控制与流程隔离,降低耦合
void LED_fun()
{
LED_switch(LED1_Pin|LED2_Pin|LED3_Pin|LED4_Pin|LED5_Pin|LED6_Pin|LED7_Pin|LED8_Pin,GPIO_PIN_SET);
if(LD1_f==1)
{
LED_switch(LED1_Pin,GPIO_PIN_RESET);
}
}
//按键响应
void B1_fun()
{
B1_key++;
LCD_Clear(Black);
if(B1_key==3)
{
changePRICE();
}
if(B1_key>3)
{
B1_key=1;
}
}
void B2_fun()
{
if(B1_key==1)
{
SHOP_X++;
if(SHOP_X>REP_X)
{
LCD_Clear(Black);
SHOP_X=0;
}
}
else if(B1_key==2)
{
PRICE_X+=0.1;
if(PRICE_X>2.0)
PRICE_X=1.0;
}
else if(B1_key==3)
REP_X++;
}
void B3_fun()
{
if(B1_key==1)
{
SHOP_Y++;
if(SHOP_Y>REP_Y)
{
LCD_Clear(Black);
SHOP_Y=0;
}
}
else if(B1_key==2)
{
PRICE_Y+=0.1;
if(PRICE_Y>2.0)
PRICE_Y=1.0;
}
else if(B1_key==3)
REP_Y++;
}
void B4_fun()
{
if(B1_key==1)
{
LD1_f=1;
__HAL_TIM_SET_COMPARE(&htim2,TIM_CHANNEL_2,29);
HAL_TIM_Base_Start_IT(&htim6);
REP_X-=SHOP_X;
REP_Y-=SHOP_Y;
if(oldREP_X!=REP_X||oldREP_Y!=REP_Y)
{
oldREP_X=REP_X;
oldREP_Y=REP_Y;
rem();
SHOP_X=SHOP_X;
SHOP_Y=SHOP_Y;
}
sprintf(txBuf,"X:%d,Y:%d,Z:%0.1f\n",SHOP_X,SHOP_Y,(SHOP_X*PRICE_X+SHOP_Y*PRICE_Y));
HAL_UART_Transmit_DMA(&huart1,(uint8_t*)txBuf,strlen(txBuf));
SHOP_X=0;
SHOP_Y=0;
LCD_Clear(Black);
}
}
//按键扫描
void KEYscan()
{
uint32_t key_delay=99;
if(HAL_GPIO_ReadPin(KEY1_GPIO_Port,KEY1_Pin)==GPIO_PIN_RESET)
{
HAL_Delay(key_delay);
if(HAL_GPIO_ReadPin(KEY1_GPIO_Port,KEY1_Pin)==GPIO_PIN_RESET)
{
B1_fun();
}
}
if(HAL_GPIO_ReadPin(KEY2_GPIO_Port,KEY2_Pin)==GPIO_PIN_RESET)
{
HAL_Delay(key_delay);
if(HAL_GPIO_ReadPin(KEY2_GPIO_Port,KEY2_Pin)==GPIO_PIN_RESET)
{
B2_fun();
}
}
if(HAL_GPIO_ReadPin(KEY3_GPIO_Port,KEY3_Pin)==GPIO_PIN_RESET)
{
HAL_Delay(key_delay);
if(HAL_GPIO_ReadPin(KEY3_GPIO_Port,KEY3_Pin)==GPIO_PIN_RESET)
{
B3_fun();
}
}
if(HAL_GPIO_ReadPin(KEY4_GPIO_Port,KEY4_Pin)==GPIO_PIN_RESET)
{
HAL_Delay(key_delay);
if(HAL_GPIO_ReadPin(KEY4_GPIO_Port,KEY4_Pin)==GPIO_PIN_RESET)
{
B4_fun();
}
}
}
/* USER CODE END 0 */
/**
* @brief The application entry point.
* @retval int
*/
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 */
LCD_Init();
LCD_SetBackColor(Black);
LCD_SetTextColor(White);
LCD_Clear(Black);
/* 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_DMA_Init();
MX_TIM2_Init();
MX_TIM6_Init();
MX_TIM7_Init();
MX_USART1_UART_Init();
/* USER CODE BEGIN 2 */
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
HAL_TIM_Base_Start(&htim2);
HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_2);
HAL_UART_Receive_DMA(&huart1,rxBuf,1);
while (1)
{
KEYscan();
LD2_fun();
if(B1_key==1)
{
LED_fun();
LCD_DisplayStringLine(Line2,(uint8_t*)" SHOP");
sprintf(LCD_str," X:%d",SHOP_X);
LCD_DisplayStringLine(Line4,(uint8_t*)LCD_str);
sprintf(LCD_str," Y:%d",SHOP_Y);
LCD_DisplayStringLine(Line5,(uint8_t*)LCD_str);
}
else if(B1_key==2)
{
LED_fun();
LCD_DisplayStringLine(Line2,(uint8_t*)" PRICE");
sprintf(LCD_str," X:%.1f",PRICE_X);
LCD_DisplayStringLine(Line4,(uint8_t*)LCD_str);
sprintf(LCD_str," Y:%.1f",PRICE_Y);
LCD_DisplayStringLine(Line5,(uint8_t*)LCD_str);
}
else if(B1_key==3)
{
LED_fun();
LCD_DisplayStringLine(Line2,(uint8_t*)" REP");
sprintf(LCD_str," X:%d",REP_X);
LCD_DisplayStringLine(Line4,(uint8_t*)LCD_str);
sprintf(LCD_str," Y:%d",REP_Y);
LCD_DisplayStringLine(Line5,(uint8_t*)LCD_str);
}
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
stm32g4xx_it.c
/**
* @brief This function handles TIM6 global interrupt, DAC1 and DAC3 channel underrun error interrupts.
*/
void TIM6_DAC_IRQHandler(void)
{
/* USER CODE BEGIN TIM6_DAC_IRQn 0 */
/* USER CODE END TIM6_DAC_IRQn 0 */
HAL_TIM_IRQHandler(&htim6);
/* USER CODE BEGIN TIM6_DAC_IRQn 1 */
HAL_TIM_Base_Stop_IT(&htim6);
LD1_f=0;
__HAL_TIM_SET_COMPARE(&htim2,TIM_CHANNEL_2,4);
/* USER CODE END TIM6_DAC_IRQn 1 */
}
/**
* @brief This function handles TIM7 global interrupt.
*/
void TIM7_IRQHandler(void)
{
/* USER CODE BEGIN TIM7_IRQn 0 */
/* USER CODE END TIM7_IRQn 0 */
HAL_TIM_IRQHandler(&htim7);
/* USER CODE BEGIN TIM7_IRQn 1 */
LED_switch(LED1_Pin|LED2_Pin|LED3_Pin|LED4_Pin|LED5_Pin|LED6_Pin|LED7_Pin|LED8_Pin,GPIO_PIN_SET);
HAL_GPIO_TogglePin(LED2_GPIO_Port,LED2_Pin);
HAL_GPIO_WritePin(LED_LE_GPIO_Port,LED_LE_Pin,GPIO_PIN_SET);
HAL_GPIO_WritePin(LED_LE_GPIO_Port,LED_LE_Pin,GPIO_PIN_RESET);
if(LD1_f==1)
LED_switch(LED1_Pin,GPIO_PIN_RESET);
/* USER CODE END TIM7_IRQn 1 */
}