STM32
直播中

廖阿朋

7年用户 1231经验值
私信 关注
[问答]

分享一个不错的STM32串口实验

分享一个不错的STM32串口实验

回帖(1)

刘飞

2021-12-16 13:53:06

实验阶段1,定时器计时1s触发中断,在中断中往外发送数据
定时器设定为36000分频,周期设定为2000,并开启中断,配置代码如下

    tim_timebase_struct.TIM_CounterMode = TIM_CounterMode_Up;    tim_timebase_struct.TIM_ClockDivision = TIM_CKD_DIV1;    tim_timebase_struct.TIM_Prescaler = DEBUG_UART_TX_TIM_PSC;    tim_timebase_struct.TIM_Period = DEBUG_UART_TX_TIM_PERIOD;    TIM_TimeBaseInit(DEBUG_UART_TX_TIM, &tim_timebase_struct);        TIM_Cmd(DEBUG_UART_TX_TIM, ENABLE);        TIM_ITConfig(DEBUG_UART_TX_TIM, TIM_IT_Update, ENABLE);
串口配置与PC端调试助手设置一致即可,一般都配置为无硬件流控,无奇偶校验,1位停止位,八位数据位

    usart_struct.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;    usart_struct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;    usart_struct.USART_Parity = USART_Parity_No;    usart_struct.USART_StopBits = USART_StopBits_1;    usart_struct.USART_WordLength = USART_WordLength_8b;    usart_struct.USART_BaudRate = DEBUG_UART_BAUDRATE;    USART_Init(DEBUG_UART, &usart_struct);        USART_Cmd(DEBUG_UART, ENABLE);
中断服务函数中还是常规的检测中断标志位然后清除中断标志位

void DEBUG_UART_TX_TIM_IRQ_HANDLER(void){    if(TIM_GetITStatus(DEBUG_UART_TX_TIM, TIM_IT_Update) != RESET)    {        TIM_ClearITPendingBit(DEBUG_UART_TX_TIM, TIM_IT_Update);                printf("hellorn");    }}
串口发送函数使用了输出流重定向,需要在魔术棒配置中勾选使用微库(Use MicroLIB)

int fputc(int ch, FILE* stream){    while(USART_GetFlagStatus(DEBUG_UART, USART_FLAG_TXE) == RESET);        USART_SendData(DEBUG_UART, ch);        return ch;}
实验阶段2,通过按键触发外部中断的方式来产生一次数据发送,按键GPIO配置为一般输出,下拉即可,并且需要调用一个函数将GPIO连接到EXTI

    gpio_struct.GPIO_Mode = GPIO_Mode_IN;    gpio_struct.GPIO_PuPd = GPIO_PuPd_DOWN;    gpio_struct.GPIO_Speed = GPIO_Speed_Level_1;    gpio_struct.GPIO_Pin = PUSHBUTTON_PIN;    GPIO_Init(PUSHBUTTON_GPIO, &gpio_struct);        SYSCFG_EXTILineConfig(PUSHBUTTON_EXTI_PORTSOURCE, PUSHBUTTON_EXTI_PINSOURCE);
本实验使用的是ST官方的NUCLEO开发板,MCU型号为STM32F303RE,使用标准库开发,串口的GPIO配置如下

    gpio_struct.GPIO_Mode = GPIO_Mode_AF;    gpio_struct.GPIO_OType = GPIO_OType_PP;    gpio_struct.GPIO_PuPd = GPIO_PuPd_NOPULL;    gpio_struct.GPIO_Speed = GPIO_Speed_Level_1;    gpio_struct.GPIO_Pin = DEBUG_UART_TX | DEBUG_UART_RX;    GPIO_Init(DEBUG_UART_GPIO, &gpio_struct);        GPIO_PinAFConfig(DEBUG_UART_GPIO, DEBUG_UART_TX_PINSOURCE, GPIO_AF_7);    GPIO_PinAFConfig(DEBUG_UART_GPIO, DEBUG_UART_RX_PINSOURCE, GPIO_AF_7);
中断服务函数如下

void PUSHBUTTON_IRQ_HANDLER(void){    if(EXTI_GetITStatus(PUSHBUTTON_EXTI_LINE) != RESET)    {        EXTI_ClearITPendingBit(PUSHBUTTON_EXTI_LINE);                printf("Push button clicked!!rn");    }}
该实验功能点有一个明显BUG,即外部中断可能会连续触发,导致一次按键可能导致重复发送数据
---***---该BUG为硬件消抖做的不好所致,在官方的NUCLEO64开发板上有BUG,但在野火MINI板上运行OK
实验阶段3,做一个接受回传的功能,开启串口中断,在中断中将收到的数据进行回传

void DEBUG_UART_IRQ_HANDLER(void){    if(USART_GetITStatus(DEBUG_UART, USART_IT_RXNE) != RESET)    {        USART_ClearITPendingBit(DEBUG_UART, USART_IT_RXNE);                uint16_t data = USART_ReceiveData(DEBUG_UART);        USART_SendData(DEBUG_UART, data);    }}
举报

更多回帖

发帖
×
20
完善资料,
赚取积分