4组串口UART使用DMA收发

4组串口UART使用DMA收发, 精品实战代码, 易用,高效,稳定 !

源自实际系统 @STC32G12K128 系列

非常容易使用, 将C文件添加至项目, 初始化后, 即可用.

仅3个函数, 包含一切UART串口操作, 适用90%以上场景 !

===从此告别串口驱动代码开发.

void UART1_Init(u32 btl); //初始化串口

u8 UART1_Send(void *pt, u16 Size); //发送数据

u16 UART1_Receive(u8 *buf, u16 Size); //接收数据

main() 函数演示 4个串口同时使用 DMA 收发数据, 收到数据后原路返回, 不限数据长度, 持续收发.

主要收发函数使用说明:

/**

* 原型: u8 UART1_Send( void *pt, u16 Size);

* @功能 串口发送数据. 写数据至发送缓冲区(循环池), 写完立即返回, 由DMA管理数据流向串口,

用户无须关心. 只要缓冲区有足够的空间, 可持续写入数据

* @参数 pt: 发送数据指针

* @参数 Size: 发送数量(字节)

* @返回值 当缓冲区没有足够的空间装入数据时返回1, 其它时候返回0

*/

/**

* 原型: u16 UART1_Receive(u8 *buf, u16 Size);

* @功能 读串口数据, 从缓冲区内读取数据. (DMA接收数据后存放至接收缓冲区,

应用代码必须定时查询读取, 否则循环池发生数据覆盖, 会丢失一部分数据, 没有提示, 但不影响后续收发)

* @参数 buf: 接收数据指针

* @参数 Size: Size期盼接收的字节数

* @返回值 实际接收字节数. 缓冲区空时(没有数据可读)返回0, 返回值<Size说明本次读取完成后,缓冲区已空.

返回值==Size说明本次读取完成后,缓冲区仍有数据可读. 任何时候,返回值不会大于Size

*/

/*---------------------------------------------------------

MAIN.C

main 函数演示 4个串口同时使用 DMA 收发数据, 收到数据后原路返回, 不限数据长度, 持续收发.

例程中所有串口9600波特率,默认引脚,定时器2作为波特率发生器

----------------------------------------------------------*/

#include "Config.h"

#include ".\library\STC32G_GPIO.h"

#include "UART1.h"

#include "UART2.h"

#include "UART3.h"

#include "UART4.h"

/*---------------------------------------------------------

本地函数声明

----------------------------------------------------------*/

void Timer0_Init(void);

void XOSCClkConfig(u8 div);

void GPIO_config(void);

void Delay1000ms();

/*---------------------------------------------------------

全局变量

----------------------------------------------------------*/

u8 ClockSignal=0;

/*---------------------------------------------------------

main

----------------------------------------------------------*/

void main(void)

{

WTST = 0; //设置程序指令延时参数,赋值为0可将CPU执行指令的速度设置为最快

EAXSFR(); //扩展SFR(XFR)访问使能

CKCON = 0; //提高访问XRAM速度

GPIO_config(); //GPIO 初始化

#if USE_Extern_Fosc

XOSCClkConfig(1); //切换时钟

#endif

UART1_Init(9600); //串口1 初始化

UART2_Init(9600); //串口1 初始化

UART3_Init(9600); //串口1 初始化

UART4_Init(9600); //串口1 初始化

Timer0_Init(); //Timer0 初始化

EA = 1;

Delay1000ms(); //等待1秒, PC端下载代码,1秒自动打开CDC串口

printf("STC32G_UART_DEMO"); //打印信到CDC

while(1)

{

if(ClockSignal>0)

{

u8 uart_dat32,len;

ClockSignal--;

//串口1接收,发送

do{

len = UART1_Receive(uart_dat,32); //读串口1收到的数据

UART1_Send(uart_dat,len); //串口1发送读到的数据

}while(len==32);

//串口2接收,发送

do{

len = UART2_Receive(uart_dat,32); //读串口2收到的数据

UART2_Send(uart_dat,len); //串口2发送读到的数据

}while(len==32);

//串口3接收,发送

do{

len = UART3_Receive(uart_dat,32); //读串口3收到的数据

UART3_Send(uart_dat,len); //串口3发送读到的数据

}while(len==32);

//串口4接收,发送

do{

len = UART4_Receive(uart_dat,32); //读串口4收到的数据

UART4_Send(uart_dat,len); //串口4发送读到的数据

}while(len==32);

}

}

}

/*---------------------------------------------------------

GPIO_config

----------------------------------------------------------*/

void GPIO_config(void)

{

P0_MODE_IO_PU(GPIO_Pin_All); //P0 设置为准双向口

P1_MODE_IO_PU(GPIO_Pin_All); //P1 设置为准双向口

P2_MODE_IO_PU(GPIO_Pin_All); //P2 设置为准双向口

P3_MODE_IO_PU(GPIO_Pin_All); //P3 设置为准双向口

P4_MODE_IO_PU(GPIO_Pin_All); //P4 设置为准双向口

P5_MODE_IO_PU(GPIO_Pin_All); //P5 设置为准双向口

P6_MODE_IO_PU(GPIO_Pin_All); //P6 设置为准双向口

P7_MODE_IO_PU(GPIO_Pin_All); //P7 设置为准双向口

P7_MODE_IO_PU(GPIO_Pin_All); //P7 设置为准双向口

}

/*-----------------------------------------------------------*

Timer0_Init

*-----------------------------------------------------------*/

#define OS_TICKS_PER_SEC 50u /*指定滴答时钟频率,宏自动计算装载值*/

#define TM0PS_VALUE ( MAIN_Fosc / OS_TICKS_PER_SEC / 65536UL )

#define RELOAD_VALUE ( 65536UL - MAIN_Fosc / (TM0PS_VALUE+1U) / OS_TICKS_PER_SEC )

void Timer0_Init(void)

{

AUXR |= 0x80; //1T模式

TMOD &= 0XF0; //模式0

TM0PS = TM0PS_VALUE; //分频系数

TL0 = ( uint8_t )( RELOAD_VALUE ); //装载值

TH0 = ( uint8_t )( RELOAD_VALUE >> 8 ); //装载值

TF0 = 0; //清除标志

ET0 = 1; //使能中断

TR0 = 1; //定时器开启

}

/*---------------------------------------------------------

外部晶振时钟初始化程序. div: 时钟分频系数.

----------------------------------------------------------*/

#if USE_Extern_Fosc

void XOSCClkConfig(u8 div)

{

P1_MODE_IN_HIZ(GPIO_Pin_7|GPIO_Pin_6); //GPIO设置

XOSCCR = 0xC0; //启动外部晶振

while (!(XOSCCR & 1)); //等待时钟稳定

CLKDIV = div; //时钟分频

CLKSEL = 0x01; //选择外部晶振

}

#endif

/*---------------------------------------------------------

Timer0 中断

----------------------------------------------------------*/

void Timer0_ISR_Handler (void) interrupt TMR0_VECTOR //进中断时已经清除标志

{

ClockSignal++;

}

/*---------------------------------------------------------

Delay1000ms

----------------------------------------------------------*/

void Delay1000ms() //@11.0592MHz

{

unsigned long edata i;

nop();

nop();

i = 2764798UL;

while (i) i--;

}