串口发送中断的应用

目录

串口接收中断在各蓝牙芯片的EVT中已经包含,不过并没有提供主机发送中断例程,本篇博客以CH582为例调试串口发送中断。

见手册中下表,发送保持寄存器空,或者使能发送中断时会触发中断。方法很简单,主函数中的处理:①判断标志是否需要发送数据,②将待发送数据拷贝到发送缓存,③手动使能发送中断,触发一次中断。

代码跑进UART中断后,会进入发送寄存器空case,用户代码在这个case中填充待发送数据,一次最多填8字节。发完刚填充完的8字节数据后,FIFO空了,会自动触发中断,如此循环直到发送完。

注意:用户代码填写完所有数据,MCU自动触发最后一次的发送中断,只是表明FIFO空了,移位寄存器中仍有一个字节还没来得及发出去

#include "CH58x_common.h"

struct _u1_send_str_{
    uint8_t u1_sending;     //正在发送标志,置1表示正在发送
    uint8_t u1_send_len;    //发送总长度
    uint8_t u1_send_cnt;    //已发送字节数
};

typedef struct  _u1_send_str_  u1_send_str;

volatile u1_send_str u1_str1 = {0};

uint8_t u1_tx_Buff[64];    //存放待发送数据

char *Test_Str="0123456789abdef13579bdf02468ace\r\n";

/*********************************************************************
 * @fn      main
 *
 * @brief   主函数
 *
 * @return  none
 */
int main()
{
    uint8_t len;

    SetSysClock(CLK_SOURCE_PLL_60MHz);

    /* 配置串口1:先配置IO口模式,再配置串口 */
    GPIOA_SetBits(GPIO_Pin_9);
    GPIOA_ModeCfg(GPIO_Pin_8, GPIO_ModeIN_PU);      // RXD-配置上拉输入
    GPIOA_ModeCfg(GPIO_Pin_9, GPIO_ModeOut_PP_5mA); // TXD-配置推挽输出,注意先让IO口输出高电平
    UART1_DefInit();

//    UART1_ByteTrigCfg(UART_7BYTE_TRIG);
//    UART1_INTCfg(ENABLE, RB_IER_RECV_RDY | RB_IER_LINE_STAT | RB_IER_THR_EMPTY);
    PFIC_EnableIRQ(UART1_IRQn);

    DelayMs(100);
    printf("CH582M Init  @ChipID=%02X %s  %s  \r\n", R8_CHIP_ID, __DATE__,__TIME__);
    while(1)
    {
        if(!u1_str1.u1_sending)
        {
            u1_str1.u1_send_len = strlen(Test_Str);
            memcpy(u1_tx_Buff, Test_Str, u1_str1.u1_send_len); //拷贝数据
            UART1_INTCfg(ENABLE, RB_IER_THR_EMPTY);          //使能发送中断,会置发送缓存空标志,触发中断
            DelayMs(1000);
        }
    }
}

/*********************************************************************
 * @fn      UART1_IRQHandler
 *
 * @brief   UART1中断函数
 *
 * @return  none
 */
__INTERRUPT
__HIGH_CODE
void UART1_IRQHandler(void)
{
    uint8_t tx_num_now = 0;
    u1_str1.u1_sending = 1;
    switch(UART1_GetITFlag())
    {
        case UART_II_LINE_STAT: // 线路状态错误
        {
            UART1_GetLinSTA();
            break;
        }

        case UART_II_RECV_RDY: // 数据达到设置触发点
            break;

        case UART_II_RECV_TOUT: // 接收超时,暂时一帧数据接收完成
            break;

        case UART_II_THR_EMPTY: // 发送缓存区空,可继续发送
            if(u1_str1.u1_send_len)       //查看是否需要分包
            {
                if(u1_str1.u1_send_len <= 8) //全部向FIFO填充
                {
                    tx_num_now = u1_str1.u1_send_len;
                    u1_str1.u1_send_len = 0;
                }
                else                        //分包填充,一次填8字节
                {
                    tx_num_now = 8;
                    u1_str1.u1_send_len -= 8;
                }

                for(uint8_t i=0; i<tx_num_now; i++)
                {
                    R8_UART1_THR = *(u1_tx_Buff + u1_str1.u1_send_cnt + i); //向FIFO填充数据
                }

                u1_str1.u1_send_cnt += tx_num_now; //累计已发送的数据个数
            }
            else  //最后一次发送缓存区数据空,处理标志,关发送中断。注意移位寄存器中最后一个字节的数据还没有来得及发出去。
            {
                u1_str1.u1_send_cnt = 0;
                u1_str1.u1_sending = 0;
                UART1_INTCfg(DISABLE, RB_IER_THR_EMPTY);
            }
            break;

        case UART_II_MODEM_CHG: // 只支持串口0
            break;

        default:
            break;
    }
}

 

posted @ 2022-11-14 14:22  JayWell  阅读(688)  评论(0编辑  收藏  举报