1 题目
2 解析
/* USER CODE BEGIN Header */
/********************************************************************************* @file : main.c* @brief : Main program body******************************************************************************* @attention** Copyright (c) 2024 STMicroelectronics.* All rights reserved.** This software is licensed under terms that can be found in the LICENSE file* in the root directory of this software component.* If no LICENSE file comes with this software, it is provided AS-IS.********************************************************************************/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "tim.h"
#include "gpio.h"/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "i2c_hal.h"
#include "stdio.h"
#include "string.h"
#include "lcd.h"
/* USER CODE END Includes *//* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
int hour[6],min[6],second[6];
char buf1[20],buf2[20],buf3[20],buf4[20];
struct keys{int state;int step;int time;
}key[5];
int cnt1,cnt2,cnt3,cnt4,cnt5;
uint8_t val;
int thour,tmin,tsecond,t;//由于题目存在暂时存储时间(有不存入EEPROM的情况),那么设定一个临时存放用于存储时间的变量
int a;
int num;
int i;
int flag,flag1;
int cnt,cnt_down,f;//这里额外测量输出PWM的占空比
double duty;
/* USER CODE END PTD *//* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD *//* USER CODE END PD *//* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM *//* USER CODE END PM *//* Private variables ---------------------------------------------------------*//* USER CODE BEGIN PV *//* USER CODE END PV *//* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */
void EEPROM_Write(uint8_t addr,uint8_t info)//EEPROM模板函数
{I2CStart();I2CSendByte(0xa0);I2CWaitAck();I2CSendByte(addr);I2CWaitAck();I2CSendByte(info);I2CWaitAck();I2CStop();
}
uint8_t EEPROM_Read(uint8_t addr)
{I2CStart();I2CSendByte(0xa0);I2CWaitAck();I2CSendByte(addr);I2CWaitAck();I2CStart();I2CSendByte(0xa1);I2CWaitAck();val=I2CReceiveByte();I2CWaitAck();I2CStop();return val;
}
void highlight(int start,int end,uint8_t* buf)//高亮函数
{LCD_ClearLine(Line4);LCD_SetBackColor(Green);for(int p=start;p<=end;p++){LCD_DisplayChar(Line4,320-16*p,buf[p]);}LCD_SetBackColor(White);for(int p=0;p<start;p++){LCD_DisplayChar(Line4,320-16*p,buf[p]);}for(int p=end+1;p<14;p++){LCD_DisplayChar(Line4,320-16*p,buf[p]);}
}
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{if(htim->Instance==TIM3)//按键中断回调函数10ms{key[1].state=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0);key[2].state=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1);key[3].state=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_2);key[4].state=HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0);switch(key[1].step){case 0:{if(key[1].state==GPIO_PIN_RESET&&buf3[8]=='t'){key[1].step=1;cnt4=0;}}break;case 1:{if(key[1].state==GPIO_PIN_RESET){key[1].step=2;}else{key[1].step=0;}}break;case 2:{if(key[1].state==GPIO_PIN_SET){cnt1++;num=cnt1%5+1;//默认显示定时1,那么根据计算得出按键次数与显示定时序号的关系LCD_Clear(White);sprintf(buf1," NO: %d",num);LCD_DisplayStringLine(Line1,(uint8_t*)buf1);sprintf(buf3," Standby");//停止状态LCD_DisplayStringLine(Line7,(uint8_t*)buf3);if(num==1)//从EEPROM中读取时间{thour=EEPROM_Read(0x01);t=100000; while(t--);//在中断回调函数内这里不直接用HAL_Delaytmin=EEPROM_Read(0x02);t=100000; while(t--);tsecond=EEPROM_Read(0x03);t=100000; while(t--);sprintf(buf2," %02d:%02d:%02d",thour,tmin,tsecond);LCD_DisplayStringLine(Line4,(uint8_t*)buf2);}if(num==2){thour=EEPROM_Read(0x11);t=100000; while(t--);tmin=EEPROM_Read(0x12);t=100000; while(t--);tsecond=EEPROM_Read(0x13);t=100000; while(t--);sprintf(buf2," %02d:%02d:%02d",thour,tmin,tsecond);LCD_DisplayStringLine(Line4,(uint8_t*)buf2);}if(num==3){thour=EEPROM_Read(0x21);t=100000; while(t--);tmin=EEPROM_Read(0x22);t=100000; while(t--);tsecond=EEPROM_Read(0x23);t=100000; while(t--);sprintf(buf2," %02d:%02d:%02d",thour,tmin,tsecond);LCD_DisplayStringLine(Line4,(uint8_t*)buf2);}if(num==4){thour=EEPROM_Read(0x31);t=100000; while(t--);tmin=EEPROM_Read(0x32);t=100000; while(t--);tsecond=EEPROM_Read(0x33);t=100000; while(t--);sprintf(buf2," %02d:%02d:%02d",thour,tmin,tsecond);LCD_DisplayStringLine(Line4,(uint8_t*)buf2);}if(num==5){thour=EEPROM_Read(0x41);t=100000; while(t--);tmin=EEPROM_Read(0x42);t=100000; while(t--);tsecond=EEPROM_Read(0x43);t=100000; while(t--);sprintf(buf2," %02d:%02d:%02d",thour,tmin,tsecond);LCD_DisplayStringLine(Line4,(uint8_t*)buf2);}cnt2=0;//每次切换要把按键PB1的次数清零key[1].step=0;}}break;}switch(key[2].step){case 0:{if(key[2].state==GPIO_PIN_RESET){key[2].step=1;key[2].time=0;}}break;case 1:{if(key[2].state==GPIO_PIN_RESET){key[2].step=2;cnt4=0;}else{key[2].step=0;}}break;case 2:{key[2].time++;if(key[2].time>=80)//长按停止定时器,并将临时值存入EEPROM{LCD_ClearLine(Line7);sprintf(buf3," Standby");LCD_DisplayStringLine(Line7,(uint8_t*)buf3);if(num==1){EEPROM_Write(0x01,thour);t=100000; while(t--);EEPROM_Write(0x02,tmin);t=100000; while(t--);EEPROM_Write(0x03,tsecond);t=100000; while(t--);}if(num==2){EEPROM_Write(0x11,thour);t=100000; while(t--);EEPROM_Write(0x12,tmin);t=100000; while(t--);EEPROM_Write(0x13,tsecond);t=100000; while(t--);}if(num==3){EEPROM_Write(0x21,thour);t=100000; while(t--);EEPROM_Write(0x22,tmin);t=100000; while(t--);EEPROM_Write(0x23,tsecond);t=100000; while(t--);}if(num==4){EEPROM_Write(0x31,thour);t=100000; while(t--);EEPROM_Write(0x32,tmin);t=100000; while(t--);EEPROM_Write(0x33,tsecond);t=100000; while(t--);}if(num==5){EEPROM_Write(0x41,thour);t=100000; while(t--);EEPROM_Write(0x42,tmin);t=100000; while(t--);EEPROM_Write(0x43,tsecond);t=100000; while(t--);}cnt2=0;//也将短按次数清零if(key[2].state==GPIO_PIN_SET){key[2].step=0;}}if(key[2].time<80&&key[2].state==GPIO_PIN_SET)//设置时分秒{cnt2++;if(cnt2==1){LCD_ClearLine(Line7);sprintf(buf3," Setting");LCD_DisplayStringLine(Line7,(uint8_t*)buf3);highlight(6,7,(uint8_t*)buf2);}if(cnt2%3==2){highlight(9,10,(uint8_t*)buf2);}if(cnt2%3==0){highlight(12,13,(uint8_t*)buf2);}if(cnt2%3==1&&cnt2!=1){highlight(6,7,(uint8_t*)buf2);}key[2].step=0;}}break;}switch(key[3].step){case 0:{if(key[3].state==GPIO_PIN_RESET&&buf3[8]=='e')//只有在Setting状态下才能计数{key[3].step=1;key[3].time=0;cnt4=0;}}break;case 1:{if(key[3].state==GPIO_PIN_RESET){key[3].step=2;}else{key[3].step=0;}}break;case 2:{key[3].time++;sscanf(buf2," %d:%d:%d",&thour,&tmin,&tsecond);//提取时分秒数据显示在LCD上if(key[3].time<80&&key[3].state==GPIO_PIN_SET){if(cnt2%3==1){thour++;if(thour==24) thour=0;}if(cnt2%3==2){tmin++;if(tmin==60) tmin=0;}if(cnt2%3==0){tsecond++;if(tsecond==60) tsecond=0;}key[3].step=0;}if(key[3].time>=80){if((key[3].time-80)%3==0)//长按80ms后每隔3ms增加一个数{if(cnt2%3==1){thour++;if(thour==24) thour=0;}if(cnt2%3==2){tmin++;if(tmin==60) tmin=0;}if(cnt2%3==0){tsecond++;if(tsecond==60) tsecond=0;}if(key[3].state==GPIO_PIN_SET){key[3].step=0;}}if(key[3].state==GPIO_PIN_SET){key[3].step=0;}}sprintf(buf2," %02d:%02d:%02d",thour,tmin,tsecond);if(cnt2%3==2){highlight(9,10,(uint8_t*)buf2);}if(cnt2%3==0&&cnt2!=0){highlight(12,13,(uint8_t*)buf2);}if(cnt2%3==1){highlight(6,7,(uint8_t*)buf2);}}break;}switch(key[4].step){case 0:{if(key[4].state==GPIO_PIN_RESET){key[4].step=1;key[4].time=0;}}break;case 1:{if(key[4].state==GPIO_PIN_RESET){key[4].step=2;}else{key[4].step=0;}}break;case 2:{key[4].time++;if(key[4].time<80&&key[4].state==GPIO_PIN_SET)//获得不同的状态值跳转到倒计时的定时器回调函数中{cnt4++;if(cnt4%2==1){flag=1;}if(cnt4%2==0){flag=2;}key[4].step=0;}if(key[4].time>=80){flag=3;cnt4=0;cnt2=0;if(key[4].state==GPIO_PIN_SET){key[4].step=0;}if(cnt1==0){thour=EEPROM_Read(0x01);t=100000; while(t--);tmin=EEPROM_Read(0x02);t=100000; while(t--);tsecond=EEPROM_Read(0x03);t=100000; while(t--);sprintf(buf2," %02d:%02d:%02d",thour,tmin,tsecond);LCD_DisplayStringLine(Line4,(uint8_t*)buf2);}}}break;}}if(htim->Instance==TIM1){if(flag==1){LCD_ClearLine(Line7);sprintf(buf3," Running");LCD_DisplayStringLine(Line7,(uint8_t*)buf3);if(tsecond==0&&tmin!=0){tmin--;tsecond=60;}if(tsecond==0&&tmin==0&&thour!=0){thour--;tsecond=60;tmin=59;}tsecond--;if((tsecond==0&&tmin==0&&thour==0)||tsecond==-1){LCD_ClearLine(Line7);sprintf(buf3," Pause");LCD_DisplayStringLine(Line7,(uint8_t*)buf3);flag=0;tsecond=0;}LCD_ClearLine(Line4);sprintf(buf2," %02d:%02d:%02d",thour,tmin,tsecond);LCD_DisplayStringLine(Line4,(uint8_t*)buf2);}if(flag==2){LCD_ClearLine(Line7);sprintf(buf3," Pause");LCD_DisplayStringLine(Line7,(uint8_t*)buf3);flag=0;}if(flag==3){LCD_ClearLine(Line7);sprintf(buf3," Standby");LCD_DisplayStringLine(Line7,(uint8_t*)buf3);flag=0;LCD_ClearLine(Line4);if(num==1||num==0){sprintf(buf2," %02d:%02d:%02d",EEPROM_Read(0x01),EEPROM_Read(0x02),EEPROM_Read(0x03));LCD_DisplayStringLine(Line4,(uint8_t*)buf2);}if(num==2){sprintf(buf2," %02d:%02d:%02d",EEPROM_Read(0x11),EEPROM_Read(0x12),EEPROM_Read(0x13));LCD_DisplayStringLine(Line4,(uint8_t*)buf2);}if(num==3){sprintf(buf2," %02d:%02d:%02d",EEPROM_Read(0x21),EEPROM_Read(0x22),EEPROM_Read(0x23));LCD_DisplayStringLine(Line4,(uint8_t*)buf2);}if(num==4){sprintf(buf2," %02d:%02d:%02d",EEPROM_Read(0x31),EEPROM_Read(0x32),EEPROM_Read(0x33));LCD_DisplayStringLine(Line4,(uint8_t*)buf2);}if(num==5){sprintf(buf2," %02d:%02d:%02d",EEPROM_Read(0x41),EEPROM_Read(0x42),EEPROM_Read(0x43));LCD_DisplayStringLine(Line4,(uint8_t*)buf2);}}}if(htim->Instance==TIM7){HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);if(buf3[7]=='R'){HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_8);}else{HAL_GPIO_WritePin(GPIOC,GPIO_PIN_8,GPIO_PIN_SET);}HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);}
}
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)//题目没有要求,这里在测量PWM频率和占空比
{if(htim->Instance==TIM2){if(htim->Channel==HAL_TIM_ACTIVE_CHANNEL_1){cnt=HAL_TIM_ReadCapturedValue(&htim2,TIM_CHANNEL_1);cnt_down=HAL_TIM_ReadCapturedValue(&htim2,TIM_CHANNEL_2);f=80000000/cnt;duty=(double)cnt_down/(double)cnt;sprintf(buf4,"f:%dHzduty:%.2lf%%",f,duty*100);__HAL_TIM_SetCounter(&htim2,0);}}
}
/* USER CODE END PFP *//* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 *//* 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 *//* 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_TIM1_Init();MX_TIM3_Init();MX_TIM16_Init();MX_TIM7_Init();MX_TIM2_Init();/* USER CODE BEGIN 2 */I2CInit();LCD_Init();LCD_Clear(White);LCD_SetTextColor(Black);LCD_SetBackColor(White);HAL_TIM_Base_Start_IT(&htim1);HAL_TIM_IC_Start_IT(&htim2,TIM_CHANNEL_1);HAL_TIM_IC_Start_IT(&htim2,TIM_CHANNEL_2);HAL_TIM_Base_Start_IT(&htim3);HAL_TIM_Base_Start_IT(&htim7);HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);HAL_GPIO_WritePin(GPIOC,GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15,GPIO_PIN_SET);HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);if(EEPROM_Read(0x05)!=2){EEPROM_Write(0x05,2);HAL_Delay(20);EEPROM_Write(0x01,0);HAL_Delay(20);EEPROM_Write(0x02,0);HAL_Delay(20);EEPROM_Write(0x03,0);HAL_Delay(20);EEPROM_Write(0x11,0);HAL_Delay(20);EEPROM_Write(0x12,0);HAL_Delay(20);EEPROM_Write(0x13,0);HAL_Delay(20);EEPROM_Write(0x21,0);HAL_Delay(20);EEPROM_Write(0x22,0);HAL_Delay(20);EEPROM_Write(0x23,0);HAL_Delay(20);EEPROM_Write(0x31,0);HAL_Delay(20);EEPROM_Write(0x32,0);HAL_Delay(20);EEPROM_Write(0x33,0);HAL_Delay(20);EEPROM_Write(0x41,0);HAL_Delay(20);EEPROM_Write(0x42,0);HAL_Delay(20);EEPROM_Write(0x43,0);HAL_Delay(20);}else{sprintf(buf1," NO: 1");LCD_DisplayStringLine(Line1,(uint8_t*)buf1);sprintf(buf2," %02d:%02d:%02d",EEPROM_Read(0x01),EEPROM_Read(0x02),EEPROM_Read(0x03));LCD_DisplayStringLine(Line4,(uint8_t*)buf2);sprintf(buf3," Standby");LCD_DisplayStringLine(Line7,(uint8_t*)buf3);}/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){/* USER CODE END WHILE *//* USER CODE BEGIN 3 */if(buf3[7]=='R'){HAL_TIM_PWM_Start(&htim16,TIM_CHANNEL_1);}else{HAL_TIM_PWM_Stop(&htim16,TIM_CHANNEL_1);}LCD_ClearLine(Line9);LCD_DisplayStringLine(Line9,(uint8_t*)buf4);HAL_Delay(500);}/* USER CODE END 3 */
}