学习笔记:单片机之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