当前位置: 首页 > news >正文

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_dat[32],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--;
}

http://www.jsqmd.com/news/1117763/

相关文章:

  • TB9051FTG与STM32F765ZI电机驱动系统设计与优化
  • TCP网络编程中阻塞/非阻塞模式设置的全方位剖析
  • Stable Diffusion WebUI 从零到精通的完整实战指南:安装、提示词与高级技巧
  • AI:AI 开车撞了人,谁赔钱?——自动驾驶的法律黑洞
  • 音乐歌词批量下载神器:163MusicLyrics深度使用指南
  • 三月七小助手终极指南:星穹铁道自动化解决方案完全解析
  • 归并排序(Merge sort,台湾译作:合并排序)是建立在归并操作上的一种有效的排序算法。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用
  • 一文讲透|2026年必不可少的专业AI论文写作软件
  • JSP技术从入门到精通:企业级开发实战指南
  • Navicat重置试用期终极教程:macOS无限试用完整指南
  • PaddleOCR生产部署决策指南:API、网页版与本地部署实测对比
  • Pytest Fixture详解:从基础到高级的接口自动化测试实践
  • 如何实现Apple触控板的Windows原生体验:mac-precision-touchpad深度技术解析
  • Semaphore:让Ansible和Terraform运维从命令行到可视化协作的蜕变之旅
  • STM32F070RB驱动WS2812B的PWM+DMA高效方案
  • IIS服务器安全加固:详解HTTP TRACE漏洞原理与修复实战
  • PCF8591与MKV44F64VLH16信号转换系统设计与优化
  • 终极免费IDM激活完整指南:3步永久解锁下载神器
  • 浅析正则表达式—(原理篇)
  • PIC18F97J60与KMR221的嵌入式电压监控系统设计
  • ATIO翻译认证驾照:一篇讲透怎么办、多少钱、多久能好!
  • Potrace完全指南:3步掌握位图转矢量的终极技巧
  • 【法律人AI生产力革命】:ChatGPT文书辅助写作的5大合规红线与3步落地法(2024司法部备案实操指南)
  • NonSteamLaunchers:Steam Deck玩家的终极多平台游戏整合解决方案
  • AI审查模型偏见导致金融级代码逃逸?——基于127万行真实PR数据的偏差检测与校准白皮书(限首批500份)
  • Burp Suite与AppScan实战:构建合规安全测试环境与协同工作流
  • IDM激活脚本终极指南:3分钟免费解锁完整版,永久享受极速下载
  • TwitchNoSub:解锁Twitch订阅专属内容的完整指南
  • EM3080-W条形码扫描模块与PIC24FV16KA302的优化配置
  • 【Java毕业设计】乐享田园休闲农业服务管理平台的设计与实现 基于 SpringBoot 的田园地块认领管理系统的设计与实现(源码+文档+远程调试,全bao定制等)