找回密码
 注册
关于网站域名变更的通知
查看: 409|回复: 4
打印 上一主题 下一主题

dsPIC33CK,DMA向UART发送数据出现间断性的有字节提前覆盖前面的字节

[复制链接]

该用户从未签到

跳转到指定楼层
1#
发表于 2022-12-2 10:20 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

EDA365欢迎您登录!

您需要 登录 才可以下载或查看,没有帐号?注册

x
用DMA0向UART1-TX发数据,出现奇怪现象,要发送的字节提前了,而且总数还是对的?7 V; N4 o1 ^; C
要发送的数据为# \" p/ U' ~% b: b
chr(04) & 197331" & chr(0x1B) & "2021Echo00202111”; m- N4 v' M# a; O' ^! j
接收到的是:' i% |- X8 K, g- T# Y" k; U
chr(04) & 197332"& chr(0x1B) & "202EEch2**202**
: k( G# B0 ~2 L4 J) b7 ^5 Z- ^4 `+ Y' a- x2 G  x* K5 `: b1 B

; b! P/ a9 g* f3 W8 _经过试验发现197332最后一个2,是2021第一个2多发一遍,并且覆盖了前面的1& Q8 r5 Z  R  F+ W' S
# ?; |+ ^; B* _( O
' u8 ]9 W5 ~& V
DMA设置:' G6 w& G7 E8 Z
static void SendCC(uint8_t ComName)5 @. q  n. y3 U% k( X3 Z- o
{2 d. u! X* d3 E  ^# y6 X% I5 e
    uint8_t i ;1 U( \+ B  z0 k  R3 Y3 ~
$ [9 [0 X5 Y# R, P
        //- ********本段为DMA为初始化部分***********/
" P( b/ Y, u1 }$ X* @! b/ g
$ ~, e3 x7 z* W$ C    DMACONbits.DMAEN = 0; //禁止DMA模块
5 Q8 i  _4 Y/ l* U, J9 T* J    DMACONbits.PRSSEL = 1;  //优先级循环方案
/ Q4 e7 q7 w* f9 }! Q    DMAL = 0;                                                //RAM寻址下限
, H% a, r' C# h4 c- E  d8 n        DMAH = 0x8000;                        //RAM寻址上限
) ]3 h" K9 `& R- k5 R/ V. H        IPC3bits.U1TXIP = 7;  //DMA0优先级为7
) I% ?1 O. G% A( t3 m9 C" s        5 ^" t$ u# r/ n( j
        IEC0bits.DMA0IE = 0;   //关闭DMA0中断% C( r9 j0 J( u4 ~5 Y, s( ?$ Z
        IEC0bits.DMA1IE = 0;   //关闭DMA1中断
; @6 Q3 D0 a% N& o* \9 n        IEC1bits.DMA2IE = 0;   //关闭DMA2中断
. `  h1 [) f6 ~2 Y- u2 z        IEC1bits.DMA3IE = 0;   //关闭DMA3中断! W7 _8 K7 E) ?* z' R0 m5 U  K
//禁用计时器中断矢量
0 J8 l! f8 f8 @$ K# J            T1CONbits.TON = 0;      
9 ?  T9 N0 ~5 B" G            _T1IE = 0;
- N3 U" r( g, O; ~                IEC0bits.INT0IE = 0;
$ C- @& G9 k& T! G! V3 x- _! b. O* }' Z$ b
        //- ********************************************  u3 E/ I, x9 Y4 P( W- f! H# Z

3 d. }4 U( e* u7 @  //-------初始化DMA0-------------------
# T, K7 r  @' t' l    // ******设置DMA0通道从COMM_BUF向UART1-FIFO发送数据*****************4 x. G, x0 ^- k0 @0 r* M
        DMACH0 = 0x42;                        //禁止DMA0,并开始对DMA进行配置        
9 u% ]& m+ I0 d1 [; [        DMASRC0 = (unsigned short int) & Send_Comm_Buf + 4 ;//设置DMA0的源数据地址
: F! p! l  ~: j( p        //                DMASRC0 = *Send_Comm_Buf;//设置DMA0的原数据地址# H5 X: T9 _* l: Q
        DMADST0 = (unsigned short int) & U1TXREG;//设置DMA0目标地址为UART1-FIFO;
4 Y9 B" z" @. f# p. h1 K# G    DMAINT0bits.CHSEL = 0x05;//设置DMA0通道触发源为UART17 P9 u+ a, l- q% X$ }8 A* W0 C
    DMAINT0bits.HALFEN = 1;        //设置DMA0半满中断
: V! H" j: @. h' s; [0 U& u
& n# n# Z" q1 e( h6 v5 i; L/ a. y) A4 `/ z) B
  //-------------------------------------* g/ |. `% Q4 N6 z8 N
3 J! k* y. Y% D! I+ I  c& o
//写入前7个字节,即指令号+器件ID,
' @7 T  I- \0 y //由于器件ID为6字节,由于某些通讯部件FIFO不支持7个字节的存入,须将器件字节分段
1 w! P8 O" Y$ w  p. n //现分为两段,即直接写入FIFO的,包含指令一共4个字节
( G( ]! Q5 m1 i7 J6 k* F
8 j- ^; [: K5 _+ a' F# z        Send_Comm_Buf_P = Send_Comm_Buf;
$ @* b3 v. A# N& T    U1TXREG =  ComName ;//写入指令% [! v1 J6 p3 {2 h
        *Send_Comm_Buf_P++ = ComName;//指令写入Buf,Buf指针加一/ b# b' H+ n5 a0 k# W  @
        for (i=0;i<6;i++)! h0 g: @* g+ U  f  L4 }
    {8 L7 d  q3 _; R2 O& t5 c
        *Send_Comm_Buf_P++ = SYSID;//写入数据到Buf4 p% F) A  F( O2 [" r
        if (i<=2) , H$ f' |2 z% Q; e0 z& D
        {
/ R- A3 W; h0 L" J/ P  c                  U1TXREG = SYSID ;//写入数据到FIFO- {6 D: x8 c- R0 }. T& Q
        }! w, [+ A- Q  R, j3 P- J, n
    }4 ?8 D" ~/ m& C# P$ G
, N! O8 F8 m2 w& u4 f# ^9 [9 v
% }; m( x- S/ _( f
5 S% |  n* p- ~% f+ Y  _' l2 x8 K
        // 以下针对各不同指令进行处理,不再直接写入TXBUF,而由DMA进行处理1 y" j4 A( Q7 Q* _  I+ X( F6 f: }
        //  发送本机基本参数," D' E  t9 }2 i. [
        if (ComName == C_SysInf)
9 K* X: i. C6 a/ o3 D4 k        {
* ]  `* x, O) T$ o( _8 o0 }                        Send_Comm_Buf_Len = 0x1B;7 _2 n) k! t6 ?4 h9 l6 w

; R5 j) D$ R  X/ K6 }  J( o                        *Send_Comm_Buf_P++ = Send_Comm_Buf_Len;//07:指令长度7 x3 F: Y- k  D) q3 @( f
                        *Send_Comm_Buf_P++ = SYSMData[0];//08:出厂日期Y
1 g5 y" i# G( C" _2 L5 D                        *Send_Comm_Buf_P++ = SYSMData[1];//09:        Y0 s0 j, x+ h& R
                        *Send_Comm_Buf_P++ = SYSMData[2];//0A        M: s! W4 Z4 Z7 R7 i6 x+ K
                        *Send_Comm_Buf_P++ = SYSMData[3];//0B        D) U4 T6 M% U" b" g. V
                        *Send_Comm_Buf_P++ = SYSModel[0];//0C型号$ K3 M5 u( J8 q1 X
                        *Send_Comm_Buf_P++ = SYSModel[1];//0D型号  |1 Q: K( ^9 U
                        *Send_Comm_Buf_P++ = SYSModel[2];//0F型号
/ I$ u3 k  T, y% g3 D' P- X( h/ D                        *Send_Comm_Buf_P++ = SYSModel[3];//10型号
, V8 f+ }. d) ?" Q+ D* N+ ^6 b                        *Send_Comm_Buf_P++ = SYSMEdition[0];//11出厂版本号
) ~6 z8 b4 k7 `, P8 T8 m; n  c4 J                        *Send_Comm_Buf_P++ = SYSMEdition[1];//12
% ?+ I* C. ^; _                        *Send_Comm_Buf_P++ = SYSCData[0];//13系统更新日期Y- U$ W3 I* D* z  O0 r/ u" V$ ?6 a
                        *Send_Comm_Buf_P++ = SYSCData[1];//14            Y' o7 L9 P* j$ {+ k: H  c7 R
                        *Send_Comm_Buf_P++ = SYSCData[2];//15            M
6 b; E! O7 N" r$ a                        *Send_Comm_Buf_P++ = SYSCData[3];//16            D/ u0 _4 _' }6 z0 O& O7 H. _
                        *Send_Comm_Buf_P++ = SYSCEdition[0];//17更新的版本号
" s9 w6 r+ [* E1 s                        *Send_Comm_Buf_P++ = SYSCEdition[1];//18
1 Z4 o1 o4 B2 J- h' [        }" V% r! W- ^$ ?9 b4 t, B
        
: D# L/ v5 T+ L' s        //启动通讯-DMA
7 H& o2 P- @* I* X# X
/ O2 b9 P6 d1 D4 F) j0 ?# u        DMACNT0 = Send_Comm_Buf_Len - 7;  //设置传输数据数量
6 T6 g' r4 |7 D* r# S  |        U1STAHbits.UTXISEL = 0;//TX接收缓冲区有8个空位触发中断& s6 X/ _( C( d+ @
        // *********************************************************************# f9 N+ N6 l6 i/ B  f
        7 s$ Y1 S2 C1 P! H
        // **************启动DMA0***************************************
3 V/ ?, `3 t& Z. A        //IFS0bits.DMA0IF = 0;   //清除DMA0中断标志+ v+ z' E% w% A2 U
        DMACONbits.DMAEN = 1 ;  //启动DMA模块
- E% J0 J! j5 B1 L8 I" |; a" w# T9 Z        DMACH0bits.CHEN = 1;        //使能DMA0
) M& s0 y' A. p) `         
, Y+ f) n  |- _! ~+ I* O* T4 M+ r        // ************************************************************
! G. i# O2 V3 c5 U, _; l        
3 P- D& Q2 n: K        IEC0bits.U1TXIE = 1;//开启U1中断
' T7 k; d& B0 y2 M        IEC0bits.DMA0IE = 1;   //开启DMA中断
4 M' V. W8 x8 n' C5 L        
3 A# k$ A9 N; M4 i" ]$ D" m, R        
0 e0 z* A! ]7 H, }7 m' [
" b# K% D- t1 H, f$ C}
1 A- b& Y9 y! d% i- ~( \1 ]+ i$ t8 X
UART设置:" [7 r) U9 P+ T+ u
8 \1 T/ F# l3 w) K* t8 h
* r2 S- n1 ]9 O4 r9 Q/ N/ D

0 m* N+ q% |: [( R( ?, r9 W+ J: m+ t: p, `3 g2 `
void UART1_Initialize(void)  T/ G, j6 @8 f% x* G
{
; f' m/ N0 z& S4 H  E+ T% E% }* {7 |    // URXEN disabled; URXEN禁用;+ p' m) S9 C; _+ g
    // RXBIMD RXBKIF flag when Break makes low-to-high transition after being low for at least 23/11 bit periods;
! c2 `  o0 X# d- @, D. Q    // RXBIMD RXBKIF 标志当中断在低到高过渡至少23/11位期间后进行低到高转换;) N9 F# n- U1 b* I. K
    // UARTEN enabled;使能Uart1;
$ R1 @8 ]3 k( W9 v, K) d0 W    // MOD Asynchronous 8-bit UART; 异步8位UART;
- q6 a% T6 f/ }) |& c    // UTXBRK disabled; 禁止同步暂停符号发送3 Y7 F3 d4 v: t/ Y
    // BRKOVR TX line driven by shifter;  TX线由移位器驱动;
7 j$ ~7 P3 c  g- u    // UTXEN disabled; 禁止发送;9 {  {3 U3 E% }3 ]3 I
    // USIDL disabled; 在空闲模式下工作;7 |; Y2 r( a1 `5 N/ i) ]
    // WAKE disabled; 关闭唤醒使能9 q( i) C: p2 A# s0 d8 @
    // ABAUD disabled; 禁止自动波特率检测
+ {) |1 ?$ _* \+ R    // BRGH enabled; 高速波特率(baudclk/4)
$ c% y' p. Z4 }7 y. M4 N" \      U1MODE = (0x8080 & ~(1<<15));  // disabling UARTEN bit
1 c0 k* d# Y; i2 x2 _4 C& e  5 z3 V3 m8 N" d' Q) j% P. D
    // STSEL 1 Stop bit sent; 一个停止位
. M. }0 u. i& X5 v: j* u    // 1 checked at RX;
5 `1 K& n# l. s! D: V: G; V  F4 C    // BCLKMOD disabled; 使用传统技术器生成波特率具体取决于BRGH位;
* p- W5 m9 q- }4 Q( N! {    // SLPEN disabled; 休眠模式下关闭
. J1 \: D, s! s1 Y+ Y# S  G    // FLO Off;流控制关闭5 t. ~+ ?4 B9 Q, `
    // BCLKSEL FOSC/2; 时钟源为Fosc/2(指令周期时钟); m, H+ D4 y; Y- q7 z
    // C0EN disabled; 校验和模式0. I$ [# V/ @3 V! A0 J3 `: T
    // RUNOVF disabled;检测到溢出错误时RX停止接受新数据
' D$ c4 j( I* G' L! Z, ]    // UTXINV disabled; 输出数据不翻转,空闲状态TX高电平
1 t4 p' U  d# u, e    // URXINV disabled; 输入数据不翻转,空闲状态为高电平
8 [3 }  v7 K% K: w    // HALFDPLX disabled; 全双工模式
. x. ~3 c. @4 M% ?    U1MODEH = 0x00;
7 Q5 L; {9 F0 w$ E: L& ]   
/ @" o% l: e5 y# s) }) w% |0 v    // OERIE disabled; 接收缓冲区溢出中断禁止6 S. n0 K  J2 Q. [! G( g* s
    // RXBKIF disabled; 接收暂停字符中断禁止+ n. s1 c+ ^/ i5 P
    // RXBKIE disabled; 接收暂停字符中断标志位清除
: P9 ~! D5 I5 U0 G( v/ q    // ABDOVF disabled; BRG尚未在自动波特率采集序列期间计满返回
. q( c. h. H6 G' }! [; s' F    // OERR disabled; 接收缓冲区溢出标志清除, q8 l6 X! V7 v, b1 `4 i5 y
    // TXCIE disabled; 发送冲突中断禁止4 |3 c+ Y. Z& b; {: s
    // TXCIF disabled; 发送冲突中断标志清除
. ~% I7 @" Q" O    // FERIE disabled; 帧错误中断禁止
# @: j- [7 j5 }5 b/ N/ S    // TXMTIE disabled; 发送移位寄存器空中断禁止
" L# n9 g( C& r# U    // ABDOVE disabled; 自动波特率采集中断禁止' G6 q3 E) K8 e5 }
    // CERIE disabled; 校验和错误中断禁止/ R! h! s( R8 t8 y
    // CERIF disabled;检验和错误中断标志清除
" S9 ]1 O! c/ v* h    // PERIE disabled;  奇偶校验错误中断标志清除5 \/ q; P! R4 |' _3 i; Q
    U1STA = 0x00;
# r5 H; K5 n* w    8 j8 j4 t: Y# l: Q$ z
    // URXISEL RX_ONE_WORD; 在缓冲区有1个以上字节时触发接收中断! s9 r% ~/ Q6 D0 z! V2 k. H' z
    // UTXBE enabled; 发送缓冲区设为空,在UTXEN=0时写入1将复位TX FIFO指针和计数器  ?; i9 l( L# k9 `& R2 ]
   
1 x* j5 P+ _0 ?# `% N    // UTXISEL TX_BUF_EMPTY; 发送缓冲区全空时触发中断
7 a; I7 j( k8 l5 r    ! R2 C8 N+ ?( F" Z! V7 C8 y
    // URXBE enabled; 接收缓冲区为空,在URXEN=1时写入1将复位RX FIFO指针和计数器
7 I9 j. Q. h: u1 B$ p6 z' g    // STPMD disabled; 在第一个或第二个停止位(取决于STSEL)的中间位置触发RXIF/ d+ F8 P& h5 C* K' N
    // TXWRE disabled; 清除写发送错误标志# j: i" }( c2 V, p+ U2 Y
    U1STAH = 0x22;# a! l1 b" a+ r& B, D9 G
    , {. v- b* T+ g0 a7 \/ i
        // BaudRate = 38400; Frequency = 4,000,000 Hz; BRG 25;
. X( Q9 }  x0 n% J8 l* U  S/ x2 t
9 S' T) w: p5 n3 e% m, m* W    U1BRG =0x19;
7 ~2 y, q* s6 U4 T    U1BRGH = 0x00;! F- u/ Z' G+ j  R
    : {. l8 P1 t6 p) u, g
    U1P1 = 0x00;- W5 ]3 r6 n  {8 T' V- e' v  Z
    U1P2 = 0x00;
$ e8 K. e9 a; l# z: T1 T2 V! ~+ O    U1P3 = 0x00;* i5 N% c. z( r! a
    U1P3H = 0x00;: f; ~2 \( I. B" v
    U1TXCHK = 0x00;
/ q/ W1 v! ?* ]. [" E  Z. d    U1RXCHK = 0x00;( U  Y, G/ S1 q8 o
    7 X4 d2 {1 p: w9 q
    U1SCCON = 0x00;//9 X+ y6 V3 B  X3 w5 k
    1 ^+ {6 a+ W; r% |+ J6 C/ L
    U1SCINT = 0x00;# r% I& v) z3 b% P- s" g+ q
    4 O& a0 e" j% \6 v7 b4 p# c/ B5 f6 o
    // UART1中断寄存器$ _! u0 H% l, F- b4 f
    // ABDIF disabled; ABAUD 未使能,或已使能但未完成自动波特率' V( _5 u$ v- Y0 A) `& y6 p
    // WUIF disabled; WAKE 未使能,或已使能但未发生唤醒事件
2 Q% k$ d* V* f# i% ]& s    // ABDIE disabled; 不设置事件中断
% O# o0 ]  P6 ]* K/ j. K7 v8 L    U1INT = 0x00;
" n' w/ N- z6 i" K) W* u( e! V, w5 U. G2 B/ E: U
/ G5 U% z+ T4 S0 n9 f9 J6 O
    IEC0bits.U1RXIE = 1;// UART1接收中断允许9 r* c' y' \3 W. E" s
    % q! P, s, F9 b8 g
  
0 Y4 K9 _* F+ b4 ]$ m}
1 f" A) h+ e1 d. ]4 t* U& B3 z$ ]5 F- }4 g( w- N
  I0 R' W' ~) r) V  F# e- M
+ _/ l. x. k, c/ L7 P* B
8 H! O8 I3 {- ^9 K/ O7 Z7 [
各种办法都试过了,包括降低波特率,提高优先级,关闭了所有其他中断,把TX发送中断改为7个空位,等等,都试过了。甚至只发送chr(04) &“197331”,结果收到的还是chr(4) &“197332”。改为不用DMA都没有问题,有没有大侠能够指点一下
) D3 u; v- Y; q) D" i! h

该用户从未签到

2#
发表于 2022-12-2 11:07 | 只看该作者
从来没用过dma,问题 应该出在这里,多在网上找找这方面的资料看看。

该用户从未签到

3#
发表于 2022-12-2 13:20 | 只看该作者
有没有相关的例程呢?试试他们的有没有这样的问题,然后再对照自己的程序看看。

该用户从未签到

4#
发表于 2022-12-2 13:34 | 只看该作者
可能是由什么冲突,把其他中断都关了。1 O; x" r# }( K& ?; f" x# e
再有别的DMA,关掉,有竞争,都关了。0 |* Z2 H' g4 ^' @2 u! E
是不是变量或者BUF定义有问题。
. u* J9 d5 ]1 u不行就改用发送中断直接处理了!

该用户从未签到

5#
发表于 2022-12-2 13:42 | 只看该作者
如果每次都是固定的位置有问题,会不会是被其他变量侵入了呢,还有,程序太复杂了,能不能简化一下,就是简单的发送,发送的数据固定,那样在试试
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

推荐内容上一条 /1 下一条

EDA365公众号

关于我们|手机版|EDA365电子论坛网 ( 粤ICP备18020198号-1 )

GMT+8, 2025-6-27 17:08 , Processed in 0.093750 second(s), 23 queries , Gzip On.

深圳市墨知创新科技有限公司

地址:深圳市南山区科技生态园2栋A座805 电话:19926409050

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