找回密码
 立即注册
查看: 174|回复: 5

STC32G12K128 UART2 DMA发送乱码问题 | 已解决

[复制链接]
  • 打卡等级:偶尔看看I
  • 打卡总天数:13
  • 最近打卡:2026-04-25 17:31:15

11

主题

21

回帖

101

积分

注册会员

积分
101
发表于 2026-4-11 14:48:35 | 显示全部楼层 |阅读模式
代码如下:第一次打印的时候正常是PBSm,后面打印的时候全部都是第一个字符乱码,但是后面三个字符正常,这是为什么?





//<<AICUBE_USER_HEADER_REMARK_BEGIN>>
////////////////////////////////////////
// 在此添加用户文件头说明信息  
// 文件名称: main.c
// 文件描述:
// 文件版本: V1.0
// 修改记录:
//   1. (2026-04-11) 创建文件
////////////////////////////////////////
//<<AICUBE_USER_HEADER_REMARK_END>>


#include "config.h"                     //默认已包含stdio.h、intrins.h等头文件


//<<AICUBE_USER_INCLUDE_BEGIN>>
// 在此添加用户头文件包含  
//<<AICUBE_USER_INCLUDE_END>>


//<<AICUBE_USER_GLOBAL_DEFINE_BEGIN>>
// 在此添加用户全局变量定义、用户宏定义以及函数声明  
//<<AICUBE_USER_GLOBAL_DEFINE_END>>


uint8_t xdata DAM1[16];                 //串口2DMA发送缓冲区数组
uint8_t xdata DAM2[16];                 //串口2DMA接收缓冲区数组

////////////////////////////////////////
// 项目主函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void main(void)
{
    //<<AICUBE_USER_MAIN_INITIAL_BEGIN>>
    // 在此添加用户主函数初始化代码  
    //<<AICUBE_USER_MAIN_INITIAL_END>>

    SYS_Init();

    //<<AICUBE_USER_MAIN_CODE_BEGIN>>
    // 在此添加主函数中运行一次的用户代码
    //<<AICUBE_USER_MAIN_CODE_END>>

    while (1)
    {
        USBLIB_OUT_Done();              //查询方式处理USB接收的数据

        //<<AICUBE_USER_MAIN_LOOP_BEGIN>>
        // 在此添加主函数中用户主循环代码


         if(P35 == 0)
         {
             delay_ms(10);
             if(P35 == 0)
             {
                DAM1[0] = 'P';
                DAM1[1] = 'B';
                DAM1[2] = 'S';
                DAM1[3] = 'm';
                  DMA_UART2_SetTxAddress(DAM1);
                DMA_UART2_SetTxAmount(4);
                DMA_UART2_TriggerTx();  // 启动DMA发送
                while(P35 == 0);
             }
         }


        //<<AICUBE_USER_MAIN_LOOP_END>>
    }
}

////////////////////////////////////////
// 系统初始化函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void SYS_Init(void)
{
    EnableAccessXFR();                  //使能访问扩展XFR
    AccessCodeFastest();                //设置最快速度访问程序代码
    AccessIXramFastest();               //设置最快速度访问内部XDATA
    IAP_SetTimeBase();                  //设置IAP等待参数,产生1us时基

    //<<AICUBE_USER_PREINITIAL_CODE_BEGIN>>
    // 在此添加用户预初始化代码  
    //<<AICUBE_USER_PREINITIAL_CODE_END>>

    PORT3_Init();                       //P3口初始化
    PORT4_Init();                       //P4口初始化
    CLK_Init();                         //时钟模块初始化
    TIMER2_Init();                      //定时器2初始化
    UART2_Init();                       //串口2初始化
    delay_ms(1);
    USBLIB_Init();                      //USB库初始化
    delay_ms(1);

    //<<AICUBE_USER_INITIAL_CODE_BEGIN>>
    // 在此添加用户初始化代码  
    //<<AICUBE_USER_INITIAL_CODE_END>>

    EnableGlobalInt();                  //使能全局中断
}

////////////////////////////////////////
// 微秒延时函数
// 入口参数: us (设置延时的微秒值)
// 函数返回: 无
////////////////////////////////////////
void delay_us(uint16_t us)
{
    do
    {
        NOP(5);                         //(MAIN_Fosc + 500000) / 1000000 - 6
    } while (--us);
}


////////////////////////////////////////
// 毫秒延时函数
// 入口参数: ms (设置延时的毫秒值)
// 函数返回: 无
////////////////////////////////////////
void delay_ms(uint16_t ms)
{
    uint16_t i;

    do
    {
        i = MAIN_Fosc / 6000;
        while (--i);
    } while (--ms);
}

////////////////////////////////////////
// P3口初始化函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void PORT3_Init(void)
{
    SetP3nInitLevelHigh(PIN_ALL);       //设置P3初始化电平
    SetP3nQuasiMode(PIN_7 | PIN_6 | PIN_5 | PIN_4 | PIN_3 | PIN_2); //设置P3.7,P3.6,P3.5,P3.4,P3.3,P3.2为准双向口模式
    SetP3nHighZInputMode(PIN_1 | PIN_0); //设置P3.1,P3.0为高阻输入模式

    DisableP3nPullUp(PIN_ALL);          //关闭P3内部上拉电阻
    P3PU = 0x20; //打开P3.5上拉
    EnableP3nSchmitt(PIN_ALL);          //使能P3施密特触发
    SetP3nSlewRateNormal(PIN_ALL);      //设置P3一般翻转速度
    SetP3nDrivingNormal(PIN_ALL);       //设置P3一般驱动能力
    SetP3nDigitalInput(PIN_ALL);        //使能P3数字信号输入功能

    //<<AICUBE_USER_PORT3_INITIAL_BEGIN>>
    // 在此添加用户初始化代码  
    //<<AICUBE_USER_PORT3_INITIAL_END>>
}

////////////////////////////////////////
// P4口初始化函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void PORT4_Init(void)
{
    SetP4nInitLevelHigh(PIN_ALL);       //设置P4初始化电平
    SetP4nQuasiMode(PIN_ALL);           //设置P4为准双向口模式

    DisableP4nPullUp(PIN_ALL);          //关闭P4内部上拉电阻
    EnableP4nSchmitt(PIN_ALL);          //使能P4施密特触发
    SetP4nSlewRateNormal(PIN_ALL);      //设置P4一般翻转速度
    SetP4nDrivingNormal(PIN_ALL);       //设置P4一般驱动能力
    SetP4nDigitalInput(PIN_ALL);        //使能P4数字信号输入功能

    //<<AICUBE_USER_PORT4_INITIAL_BEGIN>>
    // 在此添加用户初始化代码  
    //<<AICUBE_USER_PORT4_INITIAL_END>>
}

////////////////////////////////////////
// 时钟初始化函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void CLK_Init(void)
{
    CLK_HSIOCK_Divider(1);              //设置高速外设时钟预分频系数

    CLK_MCLK_HIRC();                    //选择内部高精度HIRC作为主时钟
    CLK_MCLK2_BYPASS();                 //旁路MCLK2,直接使用MCLK选择

    CLK_HSIOCK_MCLK();                  //选择MCLK主时钟作为高速外设时钟源

    //<<AICUBE_USER_CLOCK_INITIAL_BEGIN>>
    // 在此添加用户初始化代码  
    //<<AICUBE_USER_CLOCK_INITIAL_END>>
}

////////////////////////////////////////
// 定时器2初始化函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void TIMER2_Init(void)
{
#define T2_PSCR                 (0)
#ifdef BAUDRATE
#undef BAUDRATE
#endif
#define BAUDRATE                (9600UL)
#define T2_RELOAD               (65536 - (SYSCLK / 12 / BAUDRATE + 2) / 4)

    TIMER2_TimerMode();                 //设置定时器2为定时模式
    TIMER2_12TMode();                   //设置定时器2为12T模式
    TIMER2_SetPrescale(T2_PSCR);        //设置定时器2的8位预分频
    TIMER2_SetReload16(T2_RELOAD);      //设置定时器2的16位重载值
    TIMER2_Run();                       //定时器2开始运行

    //<<AICUBE_USER_TIMER2_INITIAL_BEGIN>>
    // 在此添加用户初始化代码  
    S2CON = 0x50;                //8位数据,可变波特率
        AUXR &= 0xFB;                //定时器时钟12T模式
        T2L = 0xE8;                        //设置定时初始值
        T2H = 0xFF;                        //设置定时初始值
        AUXR |= 0x10;                //定时器2开始计时
    //<<AICUBE_USER_TIMER2_INITIAL_END>>
}

////////////////////////////////////////
// 串口2初始化函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void UART2_Init(void)
{
    UART2_SwitchP4647();                //设置串口数据端口: RxD2 (P4.6), TxD2 (P4.7)

    UART2_Timer2BRT();                  //串口2固定选择定时器2作为波特率发生器(W1[S2CFG.0]必须设置为1)

    UART2_EnableRx();                   //使能串口2接收数据
    UART2_Mode1();                      //设置串口2为模式1 (8位数据可变波特率)

    DMA_UART2_SetTxAmount(4);          //设置串口DMA发送总字节数
    DMA_UART2_SetTxAddress(DAM1);       //设置串口DMA发送缓冲区地址
    DMA_UART2_ClearTxFlag();            //清除串口发送DMA中断标志
    DMA_UART2_SetTxBusPriority(0);      //设置总线访问为最低优先级
    DMA_UART2_SetTxIntPriority(0);      //设置中断为最低优先级
    DMA_UART2_EnableTxInt();            //使能串口2DMA发送中断
    DMA_UART2_EnableTx();               //使能串口2DMA发送功能
//  DMA_UART2_TriggerTx();              //触发串口2DMA发送

    DMA_UART2_SetRxAmount(4);          //设置串口DMA接收总字节数
    DMA_UART2_SetRxAddress(DAM2);       //设置串口DMA接收缓冲区地址
    DMA_UART2_ClearFIFO();              //清空串口DMA接收FIFO缓冲区
    DMA_UART2_ClearRxFlag();            //清除串口接收DMA中断标志
    DMA_UART2_SetRxBusPriority(0);      //设置总线访问为最低优先级
    DMA_UART2_SetRxIntPriority(0);      //设置中断为最低优先级
    DMA_UART2_EnableRxInt();            //使能串口2DMA接收中断
    DMA_UART2_EnableRx();               //使能串口2DMA接收功能
//  DMA_UART2_TriggerRx();              //触发串口2DMA接收

    //<<AICUBE_USER_UART2_INITIAL_BEGIN>>
    // 在此添加用户初始化代码  
    //<<AICUBE_USER_UART2_INITIAL_END>>
}

////////////////////////////////////////
// USB库初始化函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void USBLIB_Init(void)
{
    usb_init();                         //初始化USB模块
    USB_SetIntPriority(0);              //设置中断为最低优先级
    set_usb_ispcmd("@STCISP#");         //设置USB不停电下载命令

    //<<AICUBE_USER_USBLIB_INITIAL_BEGIN>>
    // 在此添加用户初始化代码  
    //<<AICUBE_USER_USBLIB_INITIAL_END>>
}

////////////////////////////////////////
// 等待USB配置完成函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void USBLIB_WaitConfiged(void)
{
    while (DeviceState != DEVSTATE_CONFIGURED) //等待USB完成配置
        WDT_Clear();                    //清看门狗定时器 (防止硬件自动使能看门狗)
}

////////////////////////////////////////
// USB设备接收数据处理程序
// 入口参数: 无
// 函数返回: 无
// bUsbOutReady:USB设备接收数据标志位
// OutNumber:USB设备接收到的数据长度
// UsbOutBuffer:保存USB设备接收到的数据
////////////////////////////////////////
void USBLIB_OUT_Done(void)
{
    if (bUsbOutReady)                   //查询是否有接收到USB主机发送数据
    {
        //<<AICUBE_USER_USBLIB_ISR_CODE1_BEGIN>>
        // 在此添加中断函数用户代码  
        USB_SendData(UsbOutBuffer, OutNumber); //原路返回, 用于测试
        // 在此处添加用户处理接收数据的代码
        //<<AICUBE_USER_USBLIB_ISR_CODE1_END>>
        usb_OUT_done();                 //当前包的数据处理完成,通知USB主机可以发送下一包数据
    }
}


////////////////////////////////////////
// 串口2发送DMA中断服务程序
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void DMA_UART2TX_ISR(void) interrupt DMA_UR2T_VECTOR
{
    //<<AICUBE_USER_UART2_ISR_CODE2_BEGIN>>
    // 在此添加中断函数用户代码  
    if (DMA_UART2_CheckTxFlag())        //判断串口发送DMA中断
    {
        DMA_UART2_ClearTxFlag();        //清除串口发送DMA中断标志
    }
    //<<AICUBE_USER_UART2_ISR_CODE2_END>>
}

////////////////////////////////////////
// 串口2接收DMA中断服务程序
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void DMA_UART2RX_ISR(void) interrupt DMA_UR2R_VECTOR
{
    //<<AICUBE_USER_UART2_ISR_CODE3_BEGIN>>
    // 在此添加中断函数用户代码  
    if (DMA_UART2_CheckRxFlag())        //判断串口接收DMA中断
    {
        DMA_UART2_ClearRxFlag();        //清除串口接收DMA中断标志

    }
    //<<AICUBE_USER_UART2_ISR_CODE3_END>>
}


//<<AICUBE_USER_FUNCTION_IMPLEMENT_BEGIN>>
// 在此添加用户函数实现代码  
//<<AICUBE_USER_FUNCTION_IMPLEMENT_END>>



屏幕截图 2026-04-11 144558.png
回复

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:586
  • 最近打卡:2026-07-04 12:34:03
已绑定手机

112

主题

4958

回帖

1万

积分

荣誉版主

无情的代码机器

积分
10758
发表于 2026-4-11 15:02:24 | 显示全部楼层

打印四个字节
DMA_UART2_SetTxAmount 填3
三天不学习,赶不上刘少奇~
回复

使用道具 举报 送花

  • 打卡等级:偶尔看看I
  • 打卡总天数:13
  • 最近打卡:2026-04-25 17:31:15

11

主题

21

回帖

101

积分

注册会员

积分
101
发表于 2026-4-11 15:03:00 | 显示全部楼层
找到问题了,DMA_UART2_SetTxAmount(4);写错了,应该是DMA_UART2_SetTxAmount(3);
回复

使用道具 举报 送花

  • 打卡等级:偶尔看看I
  • 打卡总天数:13
  • 最近打卡:2026-04-25 17:31:15

11

主题

21

回帖

101

积分

注册会员

积分
101
发表于 2026-4-11 15:04:33 | 显示全部楼层
erci*** 发表于 2026-4-11 15:02
打印四个字节
DMA_UART2_SetTxAmount 填3

找到了,谢谢
回复

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:2
  • 最近打卡:2026-04-17 15:55:07
已绑定手机

0

主题

2

回帖

10

积分

新手上路

积分
10
发表于 2026-4-11 15:46:50 | 显示全部楼层
我是发送数组长度直接128    要发的字符串拼接起来  最后加上结束符  用srtlen求长度 dma发走  这么就不乱了
回复

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:492
  • 最近打卡:2026-07-05 09:21:10
已绑定手机

6

主题

429

回帖

2187

积分

金牌会员

积分
2187
发表于 2026-4-14 09:07:12 | 显示全部楼层
zongzh*** 发表于 2026-4-11 15:46
我是发送数组长度直接128    要发的字符串拼接起来  最后加上结束符  用srtlen求长度 dma发走  这么就不乱 ...

发送之前求取长度
学习
回复

使用道具 举报 送花

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2026-7-5 09:53 , Processed in 0.077156 second(s), 74 queries .

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表