学习笔记:单片机之UART(自用)

typedef struct
{
    uint32_t uartNo;
    rcu_periph_enum rcuUart;
    rcu_periph_enum rcuGpio;
    uint32_t gpio;
    uint32_t txPin;
    uint32_t rxPin;
    uint8_t irq;
} UartHwInfo_t;

static UartHwInfo_t g_uartHwInfo = {USART0, RCU_USART0, RCU_GPIOA, GPIOA, GPIO_PIN_9, GPIO_PIN_10, USART0_IRQn};

static void Usb2ComGpioInit(void)
{
    rcu_periph_clock_enable(g_uartHwInfo.rcuGpio);
    gpio_init(g_uartHwInfo.gpio, GPIO_MODE_AF_PP, GPIO_OSPEED_10MHZ, g_uartHwInfo.txPin);
    gpio_init(g_uartHwInfo.gpio, GPIO_MODE_IPU, GPIO_OSPEED_10MHZ, g_uartHwInfo.rxPin);
}

static void Usb2ComUartInit(uint32_t baudRate)
{
    /* ʹ��UARTʱ�ӣ�*/
    rcu_periph_clock_enable(g_uartHwInfo.rcuUart);
    /* ��λUART��*/
    usart_deinit (g_uartHwInfo.uartNo);
    /* ͨ��USART_CTL0�Ĵ�����WL�����ֳ���*/ 
    //usart_word_length_set(g_uartHwInfo.uartNo, USART_WL_8BIT);
    /* ͨ��USART_CTL0�Ĵ�����PCEN����У��λ��*/ 
    //usart_parity_config(g_uartHwInfo.uartNo, USART_PM_NONE);
    /* ��USART_CTL1�Ĵ�����дSTB[1:0]λ������ֹͣλ�ij��ȣ�*/ 
    //usart_stop_bit_set(g_uartHwInfo.uartNo, USART_STB_1BIT);
    /* ��USART_BAUD�Ĵ��������ò����ʣ�*/ 
    usart_baudrate_set(g_uartHwInfo.uartNo, baudRate);
    /* ��USART_CTL0�Ĵ���������TENλ��ʹ�ܷ��͹��ܣ�*/
    usart_transmit_config(g_uartHwInfo.uartNo, USART_TRANSMIT_ENABLE);
    /* ��USART_CTL0�Ĵ���������TENλ��ʹ�ܽ��չ��ܣ�*/
    usart_receive_config(g_uartHwInfo.uartNo, USART_RECEIVE_ENABLE);
    /* ʹ�ܴ��ڽ����жϣ�*/
    usart_interrupt_enable(g_uartHwInfo.uartNo, USART_INT_RBNE);
    /* ʹ�ܴ����жϣ�*/
    nvic_irq_enable(g_uartHwInfo.irq, 0, 0);
    /* ��USART_CTL0�Ĵ�������λUENλ��ʹ��UART��*/ 
    usart_enable(g_uartHwInfo.uartNo);
}

void Usb2ComDrvInit(void)
{
    Usb2ComGpioInit();
    Usb2ComUartInit(115200);
}

/**
***********************************************************************
����ʽ��֡ͷ0  ֡ͷ1  ���ݳ���  ������   LED���  ��/��  ���У������
        0x55   0xAA    0x03      0x06     0x00     0x01      0xFB
***********************************************************************
*/
#define FRAME_HEAD_0        0x55  
#define FRAME_HEAD_1        0xAA
#define CTRL_DATA_LEN       3     //�����򳤶�
#define PACKET_DATA_LEN     (CTRL_DATA_LEN + 4)  //������
#define FUNC_DATA_IDX       3     //�����������±�
#define LED_CTRL_CODE       0x06  //������

#define MAX_BUF_SIZE 20
static uint8_t g_rcvDataBuf[MAX_BUF_SIZE];
static bool g_pktRcvd = false;

typedef struct
{
    uint8_t ledNo;
    uint8_t ledState;
} LedCtrlInfo_t;

static void ProcUartData(uint8_t data)
{
    static uint8_t index = 0;
    g_rcvDataBuf[index++] = data;
    
    switch (index)
    {
        case 1:
            if (g_rcvDataBuf[0] != FRAME_HEAD_0)
            {
                index = 0;
            }
            break;
        case 2:
            if (g_rcvDataBuf[1] != FRAME_HEAD_1)
            {
                index = 0;
            }
            break;
        case PACKET_DATA_LEN:
            g_pktRcvd = true;
            index = 0;
            break;
        default:
            break;
    }
}

static uint8_t CalXorSum(const uint8_t *data, uint32_t len)
{
    uint8_t xorSum = 0;
    for (uint32_t i = 0; i < len; i++)
    {
        xorSum ^= data[i];
    }
    return xorSum;
}

static void CtrlLed(LedCtrlInfo_t *ctrlData)
{
    ctrlData->ledState != 0 ? TurnOnLed(ctrlData->ledNo) : TurnOffLed(ctrlData->ledNo);
}

/**
***********************************************************
* @brief USBת�������������
* @param
* @return 
***********************************************************
*/
void Usb2ComTask(void)
{
    if (!g_pktRcvd)
    {
        return;
    }
    g_pktRcvd = false;
    
    if (CalXorSum(g_rcvDataBuf, PACKET_DATA_LEN – 1) != g_rcvDataBuf[PACKET_DATA_LEN – 1])
    {
        return;
    }
    if (g_rcvDataBuf[FUNC_DATA_IDX] == LED_CTRL_CODE)
    {
        CtrlLed((LedCtrlInfo_t *)(&g_rcvDataBuf[FUNC_DATA_IDX + 1]));
    }
}

/**
***********************************************************
* @brief ����0�жϷ�����
* @param
* @return 
***********************************************************
*/
void USART0_IRQHandler(void)
{
    if (usart_interrupt_flag_get(g_uartHwInfo.uartNo, USART_INT_FLAG_RBNE) != RESET)
    {
        usart_interrupt_flag_clear(g_uartHwInfo.uartNo, USART_INT_FLAG_RBNE);
        uint8_t uData = (uint8_t)usart_data_receive(g_uartHwInfo.uartNo);
        ProcUartData(uData);
    }
}

/**
***********************************************************
* @brief printf����Ĭ�ϴ�ӡ�������ʾ�������Ҫ��������ڣ�
         ��������ʵ��fputc�����������ָ�򴮿ڣ���Ϊ�ض���
* @param
* @return 
***********************************************************
*/
int fputc(int ch, FILE *f)
{
    usart_data_transmit(g_uartHwInfo.uartNo, (uint8_t)ch);
    while (RESET == usart_flag_get(g_uartHwInfo.uartNo, USART_FLAG_TBE));
    return ch;
}

在使用单片机的串口资源的时候,IO口配置为复用,然后常说的一包数据是多帧数据组成的。串口一帧数据通常配置为8个bit位。一个起始位,然后8个有效位,一个停止位,奇偶校验设置为0,这样配置。然后进行包校验,通常是一包数据的最后一帧或者两帧,使用和校验或者异或校验,工程上最常用的是CRC校验。

传输和接收要关注四个寄存器位 TC TBE IDLE RBNE。

当发送寄存器中有数据时TBE为0 没有数据时为1.

当移位寄存器中有数据时TC为0 没有数据时为1.

常用TBE来判断是否向寄存器写数据 用TC来判断数据是否传输完成。

需要记住的函数:

/* reset USART */

void usart_deinit(uint32_t usart_periph);
/* configure USART baud rate value */
void usart_baudrate_set(uint32_t usart_periph, uint32_t baudval);
/* configure USART parity function */
void usart_parity_config(uint32_t usart_periph, uint32_t paritycfg);
/* configure USART word length */
void usart_word_length_set(uint32_t usart_periph, uint32_t wlen);
/* configure USART stop bit length */
void usart_stop_bit_set(uint32_t usart_periph, uint32_t stblen);
/* enable USART */
void usart_enable(uint32_t usart_periph);
/* disable USART */
void usart_disable(uint32_t usart_periph);
/* configure USART transmitter */
void usart_transmit_config(uint32_t usart_periph, uint32_t txconfig);
/* configure USART receiver */
void usart_receive_config(uint32_t usart_periph, uint32_t rxconfig);

/* USART transmit data function */
void usart_data_transmit(uint32_t usart_periph, uint16_t data);
/* USART receive data function */
uint16_t usart_data_receive(uint32_t usart_periph);

/* flag & interrupt functions */
/* get flag in STAT0/STAT1 register */
FlagStatus usart_flag_get(uint32_t usart_periph, usart_flag_enum flag);
/* clear flag in STAT0/STAT1 register */
void usart_flag_clear(uint32_t usart_periph, usart_flag_enum flag);
/* enable USART interrupt */
void usart_interrupt_enable(uint32_t usart_periph, usart_interrupt_enum interrupt);
/* disable USART interrupt */
void usart_interrupt_disable(uint32_t usart_periph, usart_interrupt_enum interrupt);
/* get USART interrupt and flag status */
FlagStatus usart_interrupt_flag_get(uint32_t usart_periph, usart_interrupt_flag_enum int_flag);
/* clear interrupt flag in STAT0/STAT1 register */
void usart_interrupt_flag_clear(uint32_t usart_periph, usart_interrupt_flag_enum int_flag);

作者:weixin_58038206

物联沃分享整理
物联沃-IOTWORD物联网 » 学习笔记:单片机之UART(自用)

发表回复