0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

CW32L083串口中断+定时器实现不定长数据接收

华仔的编程随笔 来源:华仔的编程随笔 作者:华仔的编程随笔 2023-07-12 09:00 次阅读

CW32L083的UART是没有空闲中断的,这样给接收数据帧带来一定的不便。比如我们需要用的AT指令,那么判断接收完一条完整的指令,可以用串口断+结尾rn来判断接收完一条完整指令。但是这个方法有一个缺点就是返回两个rn 时就会处理起来非常麻烦。

这是我用串口中断+定时器来实现 如空闲中断的接收,而且可以灵活的处理接收最后一个数据后的延时来判是否接收完整一条指令。

【实现方法】

1、初始化串口5,开配置波特率为115200,开启接收中断。

static void SerialInit(uint32_t BaudRate)

{
uint32_t PCLK_Freq;

GPIO_InitTypeDef GPIO_InitStructure = {0};

UART_InitTypeDef UART_InitStructure = {0};



PCLK_Freq = SystemCoreClock > > pow2_table[CW_SYSCTRL- >CR0_f.HCLKPRS];

PCLK_Freq > >= pow2_table[CW_SYSCTRL- >CR0_f.PCLKPRS];



// 调试串口使用UART5

//  PB8- >TX

//  PB9< -RX

// 时钟使能

__RCC_GPIOB_CLK_ENABLE();

__RCC_UART5_CLK_ENABLE();



// 先设置UART TX RX 复用,后设置GPIO的属性,避免口线上出现毛刺

PB08_AFx_UART5TXD();

PB09_AFx_UART5RXD();



GPIO_InitStructure.Pins = GPIO_PIN_8;

GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;

GPIO_Init(CW_GPIOB, &GPIO_InitStructure);



GPIO_InitStructure.Pins = GPIO_PIN_9;

GPIO_InitStructure.Mode = GPIO_MODE_INPUT;

GPIO_Init(CW_GPIOB, &GPIO_InitStructure);



UART_InitStructure.UART_BaudRate = BaudRate;

UART_InitStructure.UART_Over = UART_Over_16;

UART_InitStructure.UART_Source = UART_Source_PCLK;

UART_InitStructure.UART_UclkFreq = PCLK_Freq;

UART_InitStructure.UART_StartBit = UART_StartBit_FE;

UART_InitStructure.UART_StopBits = UART_StopBits_1;

UART_InitStructure.UART_Parity = UART_Parity_No;

UART_InitStructure.UART_HardwareFlowControl = UART_HardwareFlowControl_None;

UART_InitStructure.UART_Mode = UART_Mode_Rx | UART_Mode_Tx;

UART_Init(CW_UART5, &UART_InitStructure);

//优先级,无优先级分组

NVIC_SetPriority(UART2_UART5_IRQn, 0);

//UARTx中断使能

NVIC_EnableIRQ(UART2_UART5_IRQn);
}

2、定义一个结构体来储存串口的数据:

typedef struct _uartx_infor{

uint8_t rx_cnt;

uint8_t tx_cnt;

uint8_t rx_buff[UART_LEN_MAX];

uint8_t tx_buff[UART_LEN_MAX];

FunctionalState rx_state; //接收状态

} uartx_infor;

3、初始化GTIM1定时器,定义为一次计时,主频为64M,所以配置16分频 预载值为40000,从而实现10毫秒溢出产生中断。

/* 初始化GTIM定时1 创建10ms的中断*/

void init_gtim1(void)

{

GTIM_InitTypeDef GTIM_InitStruct = {0};
__RCC_GTIM1_CLK_ENABLE();   // GTIM1时钟使能

__disable_irq();

NVIC_EnableIRQ(GTIM1_IRQn);

__enable_irq();

GTIM_InitStruct.Mode = GTIM_MODE_TIME;

GTIM_InitStruct.OneShotMode = GTIM_COUNT_ONESHOT; //只运行一次

GTIM_InitStruct.Prescaler = GTIM_PRESCALER_DIV16;

GTIM_InitStruct.ReloadValue = 40000UL - 1;    // PWM频率为 64M/16/ 4M =100Hz

GTIM_InitStruct.ToggleOutState = DISABLE;

GTIM_TimeBaseInit(CW_GTIM1, >IM_InitStruct);

GTIM_ITConfig(CW_GTIM1, GTIM_IT_OV, ENABLE);

//GTIM_Cmd(CW_GTIM1, ENABLE);
}

4、定义串口中断函数如下,主要的思想就是触发接收中断后,停止定时器的运行,重装ARR值,再开启定时器,同时把接收到的数据放入缓冲区。如果接收大于最大缓冲区,则接收值归零。

/**
 * @brief This funcation handles UART2
 */
void UART2_UART5_IRQHandler(void)
{
    /* USER CODE BEGIN */
    uint8_t rx_data;
    if(UART_GetITStatus(CW_UART5, UART_IT_RC) != RESET)
    {
        uart5_infor.rx_state = DISABLE;
        rx_data = UART_ReceiveData_8bit(CW_UART5);
        if(uart5_infor.rx_cnt < UART_LEN_MAX)
        {
            uart5_infor.rx_buff[uart5_infor.rx_cnt] = rx_data;
            CW_GTIM1- >CR0_f.EN = 0;
            CW_GTIM1- >ARR = 40000-1;
            CW_GTIM1- >CR0_f.EN = 1;
        }
        else
        {
            uart5_infor.rx_cnt = 0;
            memset(uart5_infor.rx_buff, 0, UART_LEN_MAX);
        }
        uart5_infor.rx_cnt ++;
        UART_ClearITPendingBit(CW_UART5, UART_IT_RC);
    }
    /* USER CODE END */
}

5、定时器函数为,如果触发中断,清除中断标志,把接收完整数据值置为真:

/**
 * @brief This funcation handles GTIM1
 */
void GTIM1_IRQHandler(void)
{
    /* USER CODE BEGIN */
    if(GTIM_GetITStatus(CW_GTIM1, GTIM_IT_OV))
    {
        GTIM_ClearITPendingBit(CW_GTIM1, GTIM_IT_OV);
        uart5_infor.rx_state = ENABLE; 
    }
    /* USER CODE END */
}

6、在主函数中,我们判断接收状态是否为真,如果为真则打印出接收的数值,并且重置串口数据。

while (1)
    {
        if(uart5_infor.rx_state == ENABLE)
        {
            printf("uart5 recv cnt:%drn", uart5_infor.rx_cnt);
            printf("uart5 recv cnt:%srn", uart5_infor.rx_buff);
            uart5_infor_init();
        }
        // GPIO_TogglePin(CW_GPIOC, GPIO_PIN_2);
        // rt_thread_mdelay(500);
        rt_thread_mdelay(10);
    }

【实验效果】

我们发送不定长数据,正确的从串口返回数据:

image.png

image.png

【总结】

用定时器与串口中断结合起来,完美的实现了串口的不定长接收。
审核编辑:汤梓红

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 指令
    +关注

    关注

    1

    文章

    606

    浏览量

    35646
  • 中断
    +关注

    关注

    5

    文章

    895

    浏览量

    41384
  • 定时器
    +关注

    关注

    23

    文章

    3237

    浏览量

    114432
  • 串口
    +关注

    关注

    14

    文章

    1543

    浏览量

    76160
  • uart
    +关注

    关注

    22

    文章

    1227

    浏览量

    101161
收藏 人收藏

    评论

    相关推荐

    基于CW32L083的线控器方案设计

    基于武汉芯源推出的CW32L083设计的空调线控器产品.
    的头像 发表于 06-25 14:23 5w次阅读
    基于<b class='flag-5'>CW32L083</b>的线控器方案设计

    FreeRTOS串口中断接收不定长数据与二值信号量的使用

    FreeRTOS例程,使用串口中断接收不定长数据,以及二值信号量的使用
    的头像 发表于 09-26 09:02 3938次阅读
    FreeRTOS<b class='flag-5'>串口中断</b><b class='flag-5'>接收</b><b class='flag-5'>不定长</b>的<b class='flag-5'>数据</b>与二值信号量的使用

    基于CW32L083的空调遥控方案设计

    基于武汉芯源半导体推出的CW32L083而设计的的空调遥控方案
    的头像 发表于 06-21 16:03 1481次阅读
    基于<b class='flag-5'>CW32L083</b>的空调遥控<b class='flag-5'>器</b>方案设计

    stm32串口是如何实现接收不定长度数据的呢

    stm32串口是如何实现接收不定长度数据的呢?串口接收数据
    发表于 08-11 08:18

    STM32F103串口中断是如何去接收不定长字符

    STM32F103串口中断是如何去接收不定长字符的?有什么方法吗?
    发表于 12-08 07:40

    武汉芯源Cortex-M0+ 32位低功耗MCU CW32L083系列产品介绍

    FLASH 、最多 24KB RAM、最多87路GPIO,以及一系列增强型外设。外设主要包括:1路12位ADC,6路UART、2路SPI、2路IIC以及多路定时器等功能模块,相较其他系列产品CW32L083
    发表于 08-24 09:12

    可以用串口空闲中断+DMA来实现串口接收不定长数据吗?

    串口接收不定长数据,论坛上有人说可以用串口空闲中断+DMA来
    发表于 03-07 14:49

    CW32L083产品介绍

    CW32L083是一款基于eFlash的单芯片低功耗微控制,集成了ARM®Cortex®-M0+ 核心,主频高达64MHz,高速嵌入式存储(高达256K字节的FLASH和 高达24K字节
    发表于 09-14 06:41

    CW32L083微控制数据手册

    定时器以及一组高级控制 PWM 定时器CW32L083 可以在 -40° C 到 85° C 的温度范围内工作,供电电压宽达 1.65V ~ 5.5V。支持 Sleep 和 DeepSleep两种低功耗工作模式。
    发表于 09-14 06:27

    stm32 串口接收不定长度数据及黏包处理 + 串口DMA接收

    ,那么stm32串口是如何实现接收不定长度数据的呢? 串口接收
    发表于 12-23 19:09 27次下载
    stm32 <b class='flag-5'>串口</b><b class='flag-5'>接收</b><b class='flag-5'>不定长度数据</b>及黏包处理 + <b class='flag-5'>串口</b>DMA<b class='flag-5'>接收</b>

    STM32之串口DMA接收不定长数据

    使用stm32或者其他单片机的时候,会经常使用到串口通讯,那么如何有效地接收数据呢?假如这段数据不定长的有如何高效
    发表于 12-24 19:03 30次下载
    STM32之<b class='flag-5'>串口</b>DMA<b class='flag-5'>接收</b><b class='flag-5'>不定长</b><b class='flag-5'>数据</b>

    STM32CUBEMX(8)--USART通过定时器中断方式接收不定长数据

    本文利用中断实现串口不定长接收(非DMA),使用HAL库,将接收
    的头像 发表于 11-14 16:31 1362次阅读
    STM32CUBEMX(8)--USART通过<b class='flag-5'>定时器</b><b class='flag-5'>中断</b>方式<b class='flag-5'>接收</b><b class='flag-5'>不定长</b><b class='flag-5'>数据</b>

    瑞萨e2studio(12)----USRT通过定时器中断方式接收不定长数据

    本篇文章主要介绍如何使用e2studio对瑞萨单片机进行USRT通过定时器中断方式接收不定长数据
    的头像 发表于 11-15 11:19 1146次阅读
    瑞萨e2studio(12)----USRT通过<b class='flag-5'>定时器</b><b class='flag-5'>中断</b>方式<b class='flag-5'>接收</b><b class='flag-5'>不定长</b><b class='flag-5'>数据</b>

    瑞萨e2studio----USRT通过定时器中断方式接收不定长数据

    本篇文章主要介绍如何使用e2studio对瑞萨单片机进行USRT通过定时器中断方式接收不定长数据
    的头像 发表于 11-02 17:21 1471次阅读
    瑞萨e2studio----USRT通过<b class='flag-5'>定时器</b><b class='flag-5'>中断</b>方式<b class='flag-5'>接收</b><b class='flag-5'>不定长</b><b class='flag-5'>数据</b>

    CW32L083如何实现AUTOTRIM时钟校准?

    CW32L083如何实现AUTOTRIM时钟校准?
    的头像 发表于 11-07 17:17 607次阅读
    <b class='flag-5'>CW32L083</b>如何<b class='flag-5'>实现</b>AUTOTRIM时钟校准?