本帖最后由 damiaa 于 2024-7-15 10:50 编辑
NUCLEO H533RE】之二 串口+定时功能+精确延时
上次我们用stm32cubeide生成一个项目,用 st搞的demo项目。勾了一下下面的四个勾勾,这样连接到st虚拟串口的串口(串口2)的printf打印功能就有了,
默认的led和button代码也都有了。如下:
这次我们不用勾这几个勾勾,自己来生成代码,这样更加自由和方便。生成后的项目代码如下:
然后我们同样配置gpio led和按键 一个输出一个输入:
配置串口2,并打开中断,后面 还记得在代码里面写个回调函数。
配定时器前我们先配一下时钟,这个板子的32.768k和24M外部时钟都接了,所以把它用起来:
时钟树是这么说的:
那就开始配置时钟树了:
把定时器2配置如下,这里用定时器2是为了做个精确us延时函数,这里不需要中断,当然也不要在回调函数中处理了。
主程序中加函数就实现了,后面直接调用就行。
void HAL_Delay_us(uint32_t us)
{
uint32_t d=0;
HAL_TIM_Base_Start(&htim2);
__HAL_TIM_SetCounter(&htim2,0);
while(d < us)
{
d = __HAL_TIM_GetCounter(&htim2);
}
HAL_TIM_Base_Stop(&htim2);
}
把定时器3也配置一下,这里用到中断,所以也记得后面写回调函数哦。
主程序中加代码
a,加入前面的延时函数(前面已经列出)
b,定义IO读写函数和串口接收数据缓存结构体
typedef struct
{
uint8_t RBuf[2];
uint8_t buf[UARTMAX];
uint16_t front;
uint16_t rear;
uint8_t read_flag;
}UARTBufferDef;
UARTBufferDef Uartrec2;
#define LD2_Write(x) {if(0==(x)) HAL_GPIO_WritePin(LD2_Led_GPIO_Port, LD2_Led_Pin, GPIO_PIN_RESET); else HAL_GPIO_WritePin(LD2_Led_GPIO_Port, LD2_Led_Pin, GPIO_PIN_SET);}
GPIO_PinState Read_UserButton(void)
{
return HAL_GPIO_ReadPin(GPIOC, USER_Button_Pin);
}
b,加入定时器回调函数(处理定时器3)这里就搞了个4秒一个周期的led 亮灭。
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if(htim == &htim3)
{
static int delay_led=0;
delay_led++;
if(delay_led ==2000)
{
LD2_Write(1);
}
if(delay_led ==4000)
{
delay_led=0;
LD2_Write(0);
}
}
}
c,加入串口回调函数和处理串口2命令函数
前面已经有了串口缓存结构体 下面加入回调函数,这里处理从pc发来的命令并回答命令和点灯。
//串口回调函数
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if(huart->Instance == USART2)
{
Uartrec2.buf[Uartrec2.front%UARTMAX] = Uartrec2.RBuf[0];
if(Uartrec2.front >=UARTMAX) Uartrec2.front=0;
HAL_UART_Receive_IT(huart,Uartrec2.RBuf,1);
}
}
void Uart2Command(void)
{
static uint8_t uart2_rebuf[100]={0};
static uint8_t uart2_point=0;
uint8_t rd;
while(if (Uartrec2.front != Uartrec2.rear)&&(0 == Uartrec2.read_flag))
{
if(Uartrec2.rear >=UARTMAX) Uartrec2.rear=0;
rd = Uartrec2.buf[Uartrec2.rear];
if((0x0d != rd)&&(0x0a != rd))
{
uart2_rebuf[uart2_point++] =rd;
uart2_point =uart2_point%100;
}
else
{
Uartrec2.read_flag =1;
}
}
if(1 == Uartrec2.read_flag)
{
uint8_t send[20]={'n','o','w',' ','l','d','2',' ','i','s',' ','o','n','f',0};
if(0 != uart2_point)
{
//处理接收的数 ld2 on ld2 off
if(('l' ==uart2_rebuf[0])&&('d' ==uart2_rebuf[1])&&('2' ==uart2_rebuf[2])&&(' ' ==uart2_rebuf[3])&&('o' ==uart2_rebuf[4])&&('n'==uart2_rebuf[5])&&(6 <= uart2_point))
{
send[13]= '\r';send[14]='\n';
HAL_UART_Transmit(&huart2,send,15,0xffff);
LD2_Write(1);
HAL_Delay(20);
}
if(('l' ==uart2_rebuf[0])&&('d' ==uart2_rebuf[1])&&('2' ==uart2_rebuf[2])&&(' ' ==uart2_rebuf[3])&&('o' ==uart2_rebuf[4])&&('f'==uart2_rebuf[5])&&('f' ==uart2_rebuf[6])&&(7 <= uart2_point))
{
send[14]= '\r';send[15]='\n';send[12]= 'f';
HAL_UART_Transmit(&huart2,send,16,0xffff);
LD2_Write(0);
HAL_Delay(20);
}
}
uart2_point=0;
for(uint8_t i=0;i<100;i++)
{
uart2_rebuf[i] =0;
}
Uartrec2.read_flag =0;
}
}
4,主程序中加入串口2命令处理函数,也加个精确延时函数吧,可以自行实验和测试us延时函数。调试的时候注意,延时过长可能影响串口2通信。
HAL_UART_Receive_IT(&huart2,(uint8_t *)Uartrec2.RBuf,1);
HAL_TIM_Base_Start_IT(&htim3);
Uartrec2.read_flag =0;
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
Uart2Command();
//LD2_Write(1);
Hal_Delay_us(100);
//LD2_Write(0);
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
5,编译运行
5,查看结果
谢谢