GD32串口中断接收数据实现LED亮灭

驱动层

#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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值