驱动层
#ifndef _USB2COM_DRV_H__
#define _USB2COM_DRV_H__
#include <stdint.h>
void Usb2ComDrvInit(void);
/*注册回调函数,pFunc是一个函数指针变量*/
void regUsb2ComCb(void (*pFunc)(uint8_t));
#endif
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include "gd32f30x.h"
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;
UartHwInfo_t g_uartHwInfo = {USART0, RCU_USART0, RCU_GPIOA, GPIOA, GPIO_PIN_9, GPIO_PIN_10, USART0_IRQn};
static void Usb2ComGpioInit(void)
{
/*使能GPIO时钟*/
rcu_periph_clock_enable(g_uartHwInfo.rcuGpio);
/*配置TX对应管脚为推挽输出模式*/
gpio_init(g_uartHwInfo.Gpio, GPIO_MODE_AF_PP, GPIO_OSPEED_10MHZ, g_uartHwInfo.txPin);
/*配置RX对应管脚为浮空输入/上拉输入模式*/
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 CTLO寄存器的WL设置字长*/
usart_word_length_set(g_uartHwInfo.uartNo, USART_WL_8BIT);
/*通过USART CTLO寄存器的PCEN设置校验位*/
usart_parity_config(g_uartHwInfo.uartNo,USART_PM_NONE);
/*在USARTCTL 1寄存器中写STB[1:0]位来设置停止位的长度*/
usart_stop_bit_set(g_uartHwInfo.uartNo, USART_STB_1BIT);
/*在波特率寄存器中设置波特率*/
usart_baudrate_set(g_uartHwInfo.uartNo, baudRate);
/*在USART CTLO寄存器中设置TEN位,使能发送功能*/
usart_transmit_config(g_uartHwInfo.uartNo,USART_TRANSMIT_ENABLE);
/*在UART_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 CTLO寄存器中置位UEN位,使能UART*/
usart_enable(g_uartHwInfo.uartNo);
}
/*USB转串口硬件初始化*/
void Usb2ComDrvInit(void)
{
Usb2ComGpioInit();
Usb2ComUartInit(115200);
}
// 定义一个函数指针,用于间接调用应用层的ProcUartData函数
static void (*pProcUartDataFunc)(uint8_t);
/*注册回调函数,pFunc是一个函数指针变量*/
void regUsb2ComCb(void (*pFunc)(uint8_t))
{
pProcUartDataFunc = pFunc;
}
/*串口0中断服务函数*/
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);
/*将接收到数据做处理*/
pProcUartDataFunc(uData);
}
}
/*printf默认函数打印输出到显示器,如果要输出到串口
必须重新实现fputc函数,将输出指向串口,称为重定向*/
int fputc(int ch, FILE *f)
{
// 发送数据
usart_data_transmit(g_uartHwInfo.uartNo, (uint8_t) ch);
/*等待TBE置位,判断数据缓存区里是否有数据,0表示发送数据没有完成,1表示发送数据完成了*/
while(RESET == usart_flag_get(g_uartHwInfo.uartNo,USART_FLAG_TBE));
return ch;
}
应用层
#ifndef _USB2COM_APP_H__
#define _USB2COM_APP_H__
#include <stdint.h>
/*USB转串口应用初始化*/
void Usb2ComAppInit(void);
/*
***********************************************************
* @brief USB转串口任务函数
* @param
* @return
***********************************************************
*/
void Usb2ComTask(void);
#endif
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include "usb2Com_drv.h"
#include "led_drv.h"
#define FRAME_HEAD_0 0x55
#define FRAME_HEAD_1 0xAA
#define MAX_BUF_SIZE 20
#define CRTL_DATA_LEN 3
#define PACKET_DATA_LEN (CRTL_DATA_LEN + 4)
#define FUNC_DATA_INDEX 3
#define LED_CTRL_CODE 0x06
static uint8_t g_rcvDataBuf[MAX_BUF_SIZE] = {0};
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;
}
}
/*
***********************************************************
* @brief 对数据进行异或运算
* @param data,存储数据的首地址
* @param len, 要计算的元素的个数
* @return 异或运算结果
***********************************************************
*/
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 CtrLed(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;
//printf("i am here\n");
if(CalXorSum(g_rcvDataBuf, PACKET_DATA_LEN-1) != g_rcvDataBuf[PACKET_DATA_LEN-1])
{
return;
}
if(g_rcvDataBuf[FUNC_DATA_INDEX] == LED_CTRL_CODE)
{
CtrLed((LedCtrlInfo_t *)(&g_rcvDataBuf[FUNC_DATA_INDEX+1]));
}
}
/*USB转串口应用初始化*/
void Usb2ComAppInit(void)
{
regUsb2ComCb(ProcUartData);
}
main
#include <stdint.h>
#include <stdio.h>
#include "gd32f30x.h"
#include "key_drv.h"
#include "led_drv.h"
#include "systick.h"
#include "usb2Com_drv.h"
#include "usb2com_app.h"
static void DrvInit(void)
{
LedDrvInit();
KeyDrvInit();
SysitickInit();
Usb2ComDrvInit();
}
static void AppInit(void)
{
Usb2ComAppInit();
}
int main(void)
{
DrvInit();
AppInit();
while(1)
{
Usb2ComTask();
}
}
工程文件
链接: link