ZBLOG

用STC8H8K64U的单片机串口3的不定长接收程序,用DMA方式接收,DMA不要用循环模式

以下是基于 STC8H8K64U 单片机使用 DMA(非循环模式) 实现串口3(UART3)不定长接收的完整代码方案。通过 DMA传输完成中断串口空闲中断(IDLE) 结合,实现高效的不定长数据接收。


1. 核心思路

  • DMA单次模式:每次接收固定长度后触发中断。
  • 串口空闲中断(IDLE):检测到总线空闲时提前处理数据。
  • 双缓冲区机制:避免处理数据时被新数据覆盖。

2. 硬件配置

#include "stc8h.h"
#include <intrins.h>

#define UART3_BUF_SIZE  128      // DMA接收缓冲区大小
uint8_t uart3_rx_buf[UART3_BUF_SIZE]; 
volatile uint16_t rx_len = 0;    // 实际接收长度
volatile uint8_t rx_flag = 0;    // 接收完成标志

void UART3_Init(void) {
    P_SW2 |= 0x80;               // 允许访问扩展寄存器(XFR)
    
    // --- 串口3配置 ---
    S3CON = 0x10;                // 8位数据,无校验位,1位停止位
    T3L = (65536 - (FOSC/4/115200)); // 波特率115200(根据实际时钟调整)
    T3H = (65536 - (FOSC/4/115200)) >> 8;
    T4T3M |= 0x20;               // Timer3作为波特率发生器
    
    S3CON |= 0x01;               // 使能串口3接收
    IE2 |= 0x08;                 // 使能UART3中断(用于IDLE检测)
}

void DMA_UART3_RX_Init(void) {
    DMA_URCFG &= ~0x80;          //关闭DMA_UART_RX
    
    DMA_URTSA = (uint16_t)&S3BUF;   //源地址:串口收据缓存器 
	DMA_URTDA= (uint16_t)uart_r x_buf;//目标地址:用户缓冲区  
	DAM URTCNT= UAR TBUF SIZE ;     ///传输长度  

	DAM UR CFG|=((1<<5)|(1<<4));     ///使能DMA&完成中断  
	                             ///方向:外设->内存  
	                             ///单次模式(非循环)  

	EA=1;                        ///开启总中断  
}

关键点说明

(1) DMA初始化

  • 单次模式: DMA_URCFG不设置循环模式标志。
  • 触发源:自动检测串口接收到数据后触发DMA传输。

(2) IDLE中断处理

void UART3_ISR() interrupt UART3_VECTOR {
	if(S CON&0 x02){              ///检查IDLE标志  
		 rx_len=D MA _UR TC NT-DM A _URT C NT;//计算实际接收长度  
		 r x_fl ag=1;            ///标记帧接收完成  

		 S CON&=~ x02;           ///清除IDLE标志  

		 DM A _UR CFG&=~ x80;     ///关闭当前通道以重新配置  
		 DM A _UR TD A=(uin t6 )ua rt_r x_bu f;//重置目标地址  
		 DM A _UR TC NT=UA RT_B UF_S IZE ;//重置计数器  

		 DM A _UR CFG|= x80;      ///重新使能DM通道   
	} 
}

(4)主程序逻辑示例

void main(){
	UAR_TIni t();
	DAM_U ART_R X_In it();

	while(1){
		if(rx_fl ag){             ///收到完整帧数据  

			 ProcessDa ta(uar t_rxb uf,rxl en);///自定义数据处理函数  

			 rxf lag=0;          /清除标志继续下一次接收   
		} 
	} 
}

###常见问题排查: 如果无法进入中断请检查以下项 *确认已正确设置所有相关的中断向量和优先级. *确保在调试时启用了全局中断(EA=1). *验证波特率和时钟源配置是否正确.

如果需要进一步优化或添加其他功能(如超时机制),可以在当前框架基础上扩展。


内容由零声教学AI助手提供,问题来源于学员提问

本站部分文章来源于网络,版权归原作者所有,如有侵权请联系站长删除。
转载请注明出处:http://sdn.0voice.com/?id=8243

分享:
扫描分享到社交APP
上一篇
下一篇
发表列表
游客 游客
此处应有掌声~
评论列表

还没有评论,快来说点什么吧~

联系我们

在线咨询: 点击这里给我发消息

微信号:3007537140

上班时间: 10:30-22:30

关注我们
x

注册

已经有帐号?