目的:
【1】开机后,LED1与LED2依次点亮,然后熄灭,进行灯光检测,高电平点亮LED灯。
【2】系统通过串口1向上位机发送一个字符串“一一一一一一STM32欢迎你一一一一一一”。
【3】LED1作为一个秒闪灯,系统向上位机发送完字符串后,开始亮0.5
秒,灭0.5秒….循环闪烁,并启动系统运行时间的记录,其时分秒格式为 “XX:XX:XX”。
【4】上位机通过一个由3个字节组成的命令帧控制LED2灯的开关。
该命令帧的格式为 “0xBF 控制字 0xFB”。
0xBF为帧头,0xFB为帧尾,控制字的定义如下:
0xA1:打开LED2,返回信息 “XX:XX:XX LED2打开。”
0xA2:关闭LED2,返回信息 “XX:XX:XX LED2关闭。”
其他:返回信息 “XX:XX:XX 这个一个错误指令!”。
【5】可通过四个外部按键发送串口数据
要实现这个功能,其实运用到的是led,四个外部按键,定时器和串口。而定时器和串口都是STM32的内部资源,所以外部硬件只需要两个led和四个按键而已。
STM32CUBEMX配置:
1.配置两个led
2.配置定时器2隔0.5s进行一次闪烁
3.配置串口1
4.配置四个外部按键
5.中断都打开
|
|
|
|
|
|
sprintf()函数:
printf重定义,需要将下面的代码插入到usart.c
里面
/* USER CODE BEGIN 1 */
#if 1
#include <stdio.h>
int fputc(int ch, FILE *stream)
{
/* 堵塞判断串口是否发送完成 */
while((USART1->SR & 0X40) == 0);
/* 串口发送完成,将该字符发送 */
USART1->DR = (uint8_t) ch;
return ch;
}
#endif
/* USER CODE END 1 */
代码编写:
1.点灯的宏定义+定义字符串+定义变量
/* USER CODE BEGIN Includes */
#define LED0_ON() HAL_GPIO_WritePin(GPIOB,GPIO_PIN_5,GPIO_PIN_RESET)//LED0点亮
#define LED0_OFF() HAL_GPIO_WritePin(GPIOB,GPIO_PIN_5,GPIO_PIN_SET)//LED0熄灭
#define LED0_TOG() HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_5)//LED0翻转
#define LED1_ON() HAL_GPIO_WritePin(GPIOE,GPIO_PIN_5,GPIO_PIN_RESET)//LED1点亮
#define LED1_OFF() HAL_GPIO_WritePin(GPIOE,GPIO_PIN_5,GPIO_PIN_SET)//LED1熄灭
#define LED1_TOG() HAL_GPIO_TogglePin(GPIOE,GPIO_PIN_5)//LED1翻转
uint8_t str1[] = "一一一一一一STM32欢迎你一一一一一一\r\n";
uint8_t hh = 0, mm = 0, ss = 0, ss05 = 0;
uint8_t str_buff[64];
uint8_t Rx_dat[16];
/* USER CODE END Includes */
2.跑马灯
void Ckeck_LED()
{
LED1_ON();
HAL_Delay(500);
LED0_ON();
HAL_Delay(500);
LED1_OFF();
HAL_Delay(500);
LED0_OFF();
HAL_Delay(500);
}
3.上位机发送欢迎字符
HAL_UART_Transmit(&huart1,str1,sizeof(str1),0xFFFF); //向上位机发送欢迎字符
4.打开定时器+重写定时器回调函数
HAL_TIM_Base_Start_IT(&htim2); //启动定时器TIM2
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
LED1_TOG();
ss05++;
if(ss05 == 2)
{
ss05 = 0;
ss++;
if(ss == 60)
{
ss = 0;
mm++;
if(mm == 60)
{
mm = 0;
hh++;
}
}
}
}
5.串口接收回调函数
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if(huart->Instance == USART1)
{
if(Rx_dat[0] == 0xBF && Rx_dat[2] == 0xFB)
{
switch(Rx_dat[1])
{
case 0xa1:
LED0_ON();
sprintf((char *)str_buff,"%d:%d:%d LED0打开!\r\n",hh,mm,ss);
break;
case 0xa2:
LED0_OFF();
sprintf((char *)str_buff,"%d:%d:%d LED0关闭!\r\n",hh,mm,ss);
break;
default:
sprintf((char *)str_buff,"%d:%d:%d 这是一个错误的命令!\r\n",hh,mm,ss);
break;
}
HAL_UART_Transmit(&huart1,str_buff,sizeof(str_buff),10000);
huart1.RxState = HAL_UART_STATE_READY;//没搞懂
__HAL_UART_FLUSH_DRREGISTER(&huart1);//没搞懂
HAL_UART_Receive_IT(&huart1,Rx_dat,3);
}
}
}
6.定义外部中断回调函数
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if(GPIO_Pin == GPIO_PIN_0)//PA0,按下为高
{
{
HAL_UART_Transmit(&huart1,Tx_stra,sizeof(Tx_stra),10000);
huart1.RxState = HAL_UART_STATE_READY;
__HAL_UART_FLUSH_DRREGISTER(&huart1);
HAL_UART_Receive_IT(&huart1,Rx_dat,1);
}
}
if(GPIO_Pin == GPIO_PIN_2)//PA2,按下为低
{
{
HAL_UART_Transmit(&huart1,Tx_strb,sizeof(Tx_strb),10000);
huart1.RxState = HAL_UART_STATE_READY;
__HAL_UART_FLUSH_DRREGISTER(&huart1);
HAL_UART_Receive_IT(&huart1,Rx_dat,1);
}
}
if(GPIO_Pin == GPIO_PIN_3)//PA3,按下为低
{
{
HAL_UART_Transmit(&huart1,Tx_strc,sizeof(Tx_strc),10000);
huart1.RxState = HAL_UART_STATE_READY;
__HAL_UART_FLUSH_DRREGISTER(&huart1);
HAL_UART_Receive_IT(&huart1,Rx_dat,1);
}
}
if(GPIO_Pin == GPIO_PIN_4)//PA4,按下为低
{
{
HAL_UART_Transmit(&huart1,Tx_strd,sizeof(Tx_strd),10000);
huart1.RxState = HAL_UART_STATE_READY;
__HAL_UART_FLUSH_DRREGISTER(&huart1);
HAL_UART_Receive_IT(&huart1,Rx_dat,1);
}
}
}
7.主函数
Ckeck_LED(); //LED灯流水检测
HAL_UART_Transmit(&huart1,str1,sizeof(str1),0xFFFF); //向上位机发送欢迎字符
HAL_UART_Receive_IT(&huart1,Rx_dat,3); //启动串口1接收上位机3个字节
HAL_TIM_Base_Start_IT(&htim2); //启动定时器TIM2