注:因为我的板子的PA1引脚坏了,所以只能用PA3引脚代替
一.题目
二.主要任务:
1.按键以及pwm波的设置
具体初始化过程不在描述,提供代码
uint8_t keynum=0;//全局变量的设置
void Key_Scan(void)
{
if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0) == 0)
{
keynum++;
if(keynum>250)
{
keynum=0;
flag_A1=!flag_A1;
while(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0) == 0);
}
}
if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1) == 0)
{
keynum++;
if(keynum>250)
{
A1_duty+=10;
if(A1_duty>100)
A1_duty=0;
keynum=0;
while(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1) == 0);
}
}
if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_2) == 0)
{
keynum++;
if(keynum>250)
{
keynum=0;
flag_A2=!flag_A2;
while(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_2) == 0);
}
}
if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0) == 0)
{
keynum++;
if(keynum>250)
{
A2_duty+=10;
if(A2_duty>100)
A2_duty=0;
keynum=0;
while(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0) == 0);
}
}
}
通过定时器扫描按键
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if(htim->Instance==TIM1)
{
if(flag_A1==1)
{
HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_4);
__HAL_TIM_SetCompare(&htim2,TIM_CHANNEL_4,A1_duty*10);
}
else
{
HAL_TIM_PWM_Stop(&htim2,TIM_CHANNEL_4);
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_3,GPIO_PIN_RESET);
}
if(flag_A2==1)
{
HAL_TIM_PWM_Start(&htim15,TIM_CHANNEL_1);
__HAL_TIM_SetCompare(&htim15,TIM_CHANNEL_1,A2_duty*10);
}
else
{
HAL_TIM_PWM_Stop(&htim15,TIM_CHANNEL_1);
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_0,GPIO_PIN_RESET);
}
}
}
2.串口通讯
通过接收中断来实现,为了方便测试本文使用的串口1
void HAL_UART_RxCpltCallback(UART_HandleTypeDef* huart)
{
if(huart1.Instance==USART1)
{
for(i=0;i<15;i++)
{
rx_buf[j++]=str[i];
}
rx_h=(rx_buf[0]-48)*10+rx_buf[1]-48;
rx_m=(rx_buf[3]-48)*10+rx_buf[4]-48;
rx_s=(rx_buf[6]-48)*10+rx_buf[7]-48;
i=0;
j=0;
HAL_UART_Receive_IT(&huart1,str,17);
}
}
RTC时钟的设置,先设置时钟为720k
日期和时间要同时获取,否则会有bug
RTC_TimeTypeDef T;
RTC_DateTypeDef D;
HAL_RTC_GetTime(&hrtc,&T,RTC_FORMAT_BIN);
HAL_RTC_GetDate(&hrtc,&D,RTC_FORMAT_BIN);
逻辑函数的编写
if(T.Hours==rx_h&&T.Minutes==rx_m&&T.Seconds==rx_s)
{
if(rx_buf[11]-48==1)
{
flag_A1=1;
flag_A2=0;
}
else
{
flag_A1=0;
flag_A2=1;
}
time=0;
flag1=1;
}
if(flag1==1)
time++;
if(time/900==(rx_buf[13]-48)&&flag1==1)
{
flag_A1=0;
flag_A2=0;
flag1=0;
}
time为计时变量
3.LCD的显示 和LED的灯设置
void LCD_Disp(void)
{
LCD_SetBackColor(Blue);
LCD_SetTextColor(White);
sprintf(leg_1," PWM-PA1:%d%%",A1_duty);
sprintf(leg_2," PWM-PA2:%d%%",A2_duty);
sprintf(leg_3," Time:%d:%d:%d",T.Hours,T.Minutes,T.Seconds);
sprintf(leg_4," Channel:%s",Channel);
sprintf(leg_5," Command:");
sprintf(leg_6," %s",rx_buf);
if(Second==59&&Second!=T.Seconds)
{
LCD_Clear(Blue);
}
if(strcmp(leg_4,leg_4pre)!=0)
{
LCD_Clear(Blue);
}
Second=T.Seconds;
strcpy(leg_4pre,leg_4);
LCD_DisplayStringLine(Line1,leg_1);
LCD_DisplayStringLine(Line3,leg_2);
LCD_DisplayStringLine(Line5,leg_3);
LCD_DisplayStringLine(Line7,leg_4);
LCD_DisplayStringLine(Line8,leg_5);
LCD_DisplayStringLine(Line9,leg_6);
}
void LED_Disp(uint8_t LED)
{
GPIOC->ODR=~(LED)<<8;
HAL_GPIO_WritePin(LE_GPIO_Port,LE_Pin,GPIO_PIN_SET);
HAL_GPIO_WritePin(LE_GPIO_Port,LE_Pin,GPIO_PIN_RESET);
}
if(flag_A1==1&&flag_A2==1)
{
strcpy(Channel,"PA1andPA2");
LED_Disp(0X03);
}
if(flag_A1==1&&flag_A2==0)
{
strcpy(Channel,"PA1");
LED_Disp(0X01);
}
if(flag_A2==1&&flag_A1==0)
{
strcpy(Channel,"PA2");
LED_Disp(0X02);
}
if(flag_A1==0&&flag_A2==0)
{
strcpy(Channel,"None");
LED_Disp(0X00);
}
主要遇到的问题:当屏幕上的某一行的长度变化时可能导致残留。通过字符串比较函数可以解决问题
4.E2PROM的读写
void E2PROM_Write(uint8_t address,uint8_t data)
{
I2CStart();
I2CSendByte(Write);
I2CWaitAck();
I2CSendByte(address);
I2CWaitAck();
I2CSendByte(data);
I2CWaitAck();
I2CStop();
}
uint8_t E2PROM_Read(uint8_t address)
{
uint8_t data;
I2CStart();
I2CSendByte(Write);
I2CWaitAck();
I2CSendByte(address);
I2CWaitAck();
I2CStop();
I2CStart();
I2CSendByte(Read);
I2CWaitAck();
data=I2CReceiveByte();
I2CSendNotAck();
I2CStop();
return data;
}
E2PROM_Write(0x01,A1_duty);
HAL_Delay(20);
E2PROM_Write(0x02,A2_duty);
A1_duty=E2PROM_Read(0x01);
HAL_Delay(20);
A2_duty=E2PROM_Read(0x02);
5.总结
在比赛中,对于字符串的处理用的尤其多,所以后续还需加强训练。按键的消抖感觉做的还不够,有时候不稳可能跟我设置的定时器扫描时间有关。想要具体工程文件可以在评论区评论