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

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

[复制链接]

该用户从未签到

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

EDA365欢迎您登录!

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

x
用DMA0向UART1-TX发数据,出现奇怪现象,要发送的字节提前了,而且总数还是对的?/ ]( g) i4 x6 {& N
要发送的数据为
/ k( U: P& E$ i2 O& f1 uchr(04) & 197331" & chr(0x1B) & "2021Echo00202111”
+ n4 w  G' E. q接收到的是:
0 G3 B/ q4 s* j' T. G! ]chr(04) & 197332"& chr(0x1B) & "202EEch2**202**$ K8 P# B" ~6 Z) T% Y) _+ M  H9 H
8 }; Y7 t% r) T  e; i
( s( V+ @3 @+ P, c! C
经过试验发现197332最后一个2,是2021第一个2多发一遍,并且覆盖了前面的1
9 V" {- ]5 C% Y$ a0 u! x" X3 b- Y$ y. U. T1 L
) _* }7 l' u5 s3 o! h
DMA设置:
" a" Y* _# n0 ]' H# J+ jstatic void SendCC(uint8_t ComName)! b# s2 J7 e, c
{
* l5 D5 z7 s; R% p2 e: A    uint8_t i ;" ~% K* d6 e9 |/ j

- x1 I: b6 q* B' o        //- ********本段为DMA为初始化部分***********/& E/ a9 h0 S- _/ y  P2 g, M. @
3 N. L0 N4 @3 J( T8 f# U
    DMACONbits.DMAEN = 0; //禁止DMA模块
0 q5 j5 L) a2 l" I' F3 t    DMACONbits.PRSSEL = 1;  //优先级循环方案) Q1 ~% L, \' Q: B; ^) W. ~& g
    DMAL = 0;                                                //RAM寻址下限- r8 _# g, A6 l4 w
        DMAH = 0x8000;                        //RAM寻址上限, X! {1 T8 W3 A3 `  v1 d
        IPC3bits.U1TXIP = 7;  //DMA0优先级为7! ]- J* J% D. t
        
1 o3 t" [; u* T" ]& H! o( @        IEC0bits.DMA0IE = 0;   //关闭DMA0中断
& W, z& v5 U3 s1 ^        IEC0bits.DMA1IE = 0;   //关闭DMA1中断
3 D: S* i) b3 l/ b5 [        IEC1bits.DMA2IE = 0;   //关闭DMA2中断
  a6 S" T3 {0 N        IEC1bits.DMA3IE = 0;   //关闭DMA3中断% M  {  h. z% ^7 P+ T9 l$ g
//禁用计时器中断矢量
* m# ^" |3 Y0 e( S9 @0 b5 `            T1CONbits.TON = 0;      ! t( L* j/ J  N: _& |/ @; e
            _T1IE = 0;1 U2 H8 w# H: u
                IEC0bits.INT0IE = 0;
( G* S! [( j' I
% ?, `" o: E' l1 a0 Q7 z; I        //- ********************************************& A2 L1 X1 f( r/ o# r% g$ Y# Z" e
$ X% W; j. J; _2 e* H. u
  //-------初始化DMA0-------------------
4 Z3 {0 ^0 h8 z2 z& ]6 S- M    // ******设置DMA0通道从COMM_BUF向UART1-FIFO发送数据*****************1 X; o) u+ {$ p! s
        DMACH0 = 0x42;                        //禁止DMA0,并开始对DMA进行配置        
% W, Q4 b' ]9 N( B9 [! P        DMASRC0 = (unsigned short int) & Send_Comm_Buf + 4 ;//设置DMA0的源数据地址' n# t/ M7 {. {: B2 D  S$ a  s
        //                DMASRC0 = *Send_Comm_Buf;//设置DMA0的原数据地址
+ `. S" }7 R' d2 ^2 y" I0 x6 D! [$ R        DMADST0 = (unsigned short int) & U1TXREG;//设置DMA0目标地址为UART1-FIFO;+ J% g" F5 ^1 C7 j! m
    DMAINT0bits.CHSEL = 0x05;//设置DMA0通道触发源为UART1
) w) O/ N. I0 j* s+ a    DMAINT0bits.HALFEN = 1;        //设置DMA0半满中断. i# F% ]' Y& C6 |' R7 O, o

+ r7 V# M0 V/ r  P7 w/ `+ H# |( j) V; z! m" T
  //-------------------------------------2 P. s8 B* Q$ y% s: |

8 F! ^5 O  u3 L' Y0 G  ~5 Q8 ~ //写入前7个字节,即指令号+器件ID,
! z; \% B* _: ]4 Y9 X' z! U //由于器件ID为6字节,由于某些通讯部件FIFO不支持7个字节的存入,须将器件字节分段
' w: o1 B7 Z. Y" L //现分为两段,即直接写入FIFO的,包含指令一共4个字节
! X/ S. d9 P- N
3 \4 q: X. A0 E4 s  E9 C        Send_Comm_Buf_P = Send_Comm_Buf;
4 ~9 S3 G# i. D- r    U1TXREG =  ComName ;//写入指令  `" g6 g4 C& \. b3 i' I) x& d
        *Send_Comm_Buf_P++ = ComName;//指令写入Buf,Buf指针加一( D1 N+ h9 `4 {' V. E' b
        for (i=0;i<6;i++)
, q, z4 q9 n" l$ B" ]  c    {
! R+ r4 f& K" s: j$ q0 {        *Send_Comm_Buf_P++ = SYSID;//写入数据到Buf
% T: Y0 H2 ~" L! Z% Q        if (i<=2)
# H( p" w. N! D        {
4 n  I& N' ?3 J                  U1TXREG = SYSID ;//写入数据到FIFO
* M" }7 X; S6 I6 y        }. t- ^( U4 G5 [) w
    }* k+ ^- E! P( T- ]: W
, P! }( ~. e2 g( r' E

+ `* w- l+ D% c6 u% R% P+ y) J& o
( r1 W: |7 L  R        // 以下针对各不同指令进行处理,不再直接写入TXBUF,而由DMA进行处理
# T* y0 m; ?. p+ c. m7 [1 J: q        //  发送本机基本参数,
; f! Z. Q% Z+ ]1 L5 A% _( Y        if (ComName == C_SysInf)
" t; P  w8 I, y8 L0 T        {+ w/ ~& {1 F  x
                        Send_Comm_Buf_Len = 0x1B;
- H: V! `0 _3 ]2 r/ X0 B& u
' E% s+ ]- y: i, G: \! O                        *Send_Comm_Buf_P++ = Send_Comm_Buf_Len;//07:指令长度: J* `+ r; B) {1 y
                        *Send_Comm_Buf_P++ = SYSMData[0];//08:出厂日期Y
# t) B# [2 U0 Z) n0 ?                        *Send_Comm_Buf_P++ = SYSMData[1];//09:        Y
0 \$ n6 n7 `! K- q" N                        *Send_Comm_Buf_P++ = SYSMData[2];//0A        M" M! X- Z5 e) _8 _& {5 T! E
                        *Send_Comm_Buf_P++ = SYSMData[3];//0B        D
0 N+ N, c# Y4 B. |" t2 o+ m                        *Send_Comm_Buf_P++ = SYSModel[0];//0C型号
+ a- F# x; e( x% c                        *Send_Comm_Buf_P++ = SYSModel[1];//0D型号, I& \2 o7 k7 K* n$ |" r9 c) [- a
                        *Send_Comm_Buf_P++ = SYSModel[2];//0F型号
; g# w: b& x1 A* E3 S, T; D                        *Send_Comm_Buf_P++ = SYSModel[3];//10型号
" k8 \. V9 l# v                        *Send_Comm_Buf_P++ = SYSMEdition[0];//11出厂版本号4 A& v+ i# E6 A8 n: C( t) \/ S
                        *Send_Comm_Buf_P++ = SYSMEdition[1];//12
8 _9 v" K( g- D8 g* D: @( {                        *Send_Comm_Buf_P++ = SYSCData[0];//13系统更新日期Y
& `( m3 e* T' T( @/ [$ S. u; g                        *Send_Comm_Buf_P++ = SYSCData[1];//14            Y; z6 [8 I% g3 J8 n2 v
                        *Send_Comm_Buf_P++ = SYSCData[2];//15            M7 E( s5 [6 O$ R7 y
                        *Send_Comm_Buf_P++ = SYSCData[3];//16            D* ?" \$ {0 [% \' g' `# Z! z
                        *Send_Comm_Buf_P++ = SYSCEdition[0];//17更新的版本号' j" _/ y6 A2 U; T! B
                        *Send_Comm_Buf_P++ = SYSCEdition[1];//18. Q! s" ~: `0 B  |- ~4 n$ S, |
        }; s' x9 P7 I  @& y1 h
        
% T, f$ K, }9 ]) U* n# H' ?7 G/ A        //启动通讯-DMA1 \3 h5 _% p' w4 d7 G
1 |- r% a/ k! e* c* x- ~. ?( O% }
        DMACNT0 = Send_Comm_Buf_Len - 7;  //设置传输数据数量1 A& y  @! s+ ]( Q6 C# x
        U1STAHbits.UTXISEL = 0;//TX接收缓冲区有8个空位触发中断+ [( m3 J7 b9 o! f9 Z0 c
        // ********************************************************************** d0 q4 E+ x' V9 ^$ ~3 L
        
+ y2 {9 Q( ?" P( e+ v        // **************启动DMA0***************************************
  I8 \0 n6 l, }$ Q        //IFS0bits.DMA0IF = 0;   //清除DMA0中断标志
, c1 p! C9 C5 |% k: U+ U1 x2 q        DMACONbits.DMAEN = 1 ;  //启动DMA模块
% N. I, Z% Y) ?. J6 P. V' v) Q        DMACH0bits.CHEN = 1;        //使能DMA0
% O5 r. W) b0 W8 o2 V/ y         2 q7 H5 W; b9 _3 m" _
        // ************************************************************
  D2 @, b' B; F6 r7 Y' K$ y        
! A( g% J" w1 ?, a2 p        IEC0bits.U1TXIE = 1;//开启U1中断/ p" V( k+ j8 v9 Z) `
        IEC0bits.DMA0IE = 1;   //开启DMA中断
, [  T1 {: P& L. x! i3 n# V" O        
9 N+ X, L( p8 l        
7 Z* e' ^) E) G2 T, _* J
+ ]6 H5 f: R: J  z}
. a( x# A8 d/ N, _, q! F3 h: ~* n" M9 d  F) j! T" p
UART设置:
( ]9 _; `+ a9 D! Z
% G1 Y7 |; q5 y$ B/ d( M9 C' \- v% Y: W  u# W
  Q9 \/ I  N# h! c; t# [; Z$ [
4 z/ s- Z% i! _
void UART1_Initialize(void)- `& G- P2 e9 S
{
  A' e( r) m6 k/ \! ]    // URXEN disabled; URXEN禁用;
& Q- \% x* r4 T' i    // RXBIMD RXBKIF flag when Break makes low-to-high transition after being low for at least 23/11 bit periods;
$ U- B, m3 L" k$ q3 K9 n    // RXBIMD RXBKIF 标志当中断在低到高过渡至少23/11位期间后进行低到高转换;. W8 }0 s( i. y' L
    // UARTEN enabled;使能Uart1;
3 Q( M3 c4 N  z6 V& u  e+ i    // MOD Asynchronous 8-bit UART; 异步8位UART;
# m6 R: }2 \3 p! |# a, E0 ~! x    // UTXBRK disabled; 禁止同步暂停符号发送6 i- }1 U5 {" J. ^" B
    // BRKOVR TX line driven by shifter;  TX线由移位器驱动;& x$ V& r! O* U# t& H1 m4 s
    // UTXEN disabled; 禁止发送;# Z& `' `# E  l# n2 E9 n
    // USIDL disabled; 在空闲模式下工作;
0 U6 B/ N1 B( i4 D& W4 T  b    // WAKE disabled; 关闭唤醒使能0 |6 |  f" ]# N
    // ABAUD disabled; 禁止自动波特率检测
) ^; ?+ d( i# e8 ^/ ?3 Z) \    // BRGH enabled; 高速波特率(baudclk/4)
2 v: g, M# o4 W0 {  d6 h$ \      U1MODE = (0x8080 & ~(1<<15));  // disabling UARTEN bit
* C5 N$ P# h' G    q7 i' u7 m% }+ D+ ~- h# ^1 M) K
    // STSEL 1 Stop bit sent; 一个停止位
+ M" |  F" w" y    // 1 checked at RX;
3 o, u( q1 r" v4 P# Z" `/ a    // BCLKMOD disabled; 使用传统技术器生成波特率具体取决于BRGH位;% U! P$ _: ?, ?. @3 x
    // SLPEN disabled; 休眠模式下关闭9 j* p& a0 o7 n8 j' u
    // FLO Off;流控制关闭
6 p$ v: [+ ]" V. O    // BCLKSEL FOSC/2; 时钟源为Fosc/2(指令周期时钟)* k, y: b! B2 d: _
    // C0EN disabled; 校验和模式01 w# o/ S) @3 I9 t/ j; s
    // RUNOVF disabled;检测到溢出错误时RX停止接受新数据0 P  h- J6 j1 W+ B. M2 W
    // UTXINV disabled; 输出数据不翻转,空闲状态TX高电平* G" {6 W' I, R, g+ e$ R
    // URXINV disabled; 输入数据不翻转,空闲状态为高电平
3 N4 {' Y$ ]( l1 [9 X    // HALFDPLX disabled; 全双工模式
/ k& x5 O' Q/ o' C0 U3 A    U1MODEH = 0x00;3 d! v9 A: L4 \# f$ d* Z% j7 \
   
! [& `2 i2 B; I1 ~; Q    // OERIE disabled; 接收缓冲区溢出中断禁止
8 w/ W5 l$ [- b+ C6 Y    // RXBKIF disabled; 接收暂停字符中断禁止
( O9 h' {" m+ h7 K    // RXBKIE disabled; 接收暂停字符中断标志位清除
  l9 M3 r" q1 y! D; }! r* C8 x5 R    // ABDOVF disabled; BRG尚未在自动波特率采集序列期间计满返回
7 s  ]" I2 ~  B% n- I    // OERR disabled; 接收缓冲区溢出标志清除
6 ]! j) Y; k/ e2 M7 S8 e2 f    // TXCIE disabled; 发送冲突中断禁止
) f2 q% q( \; z+ L# Z# t* |    // TXCIF disabled; 发送冲突中断标志清除
& D& v& b+ ^$ I& X/ W+ {    // FERIE disabled; 帧错误中断禁止* [1 V% l+ ^0 I
    // TXMTIE disabled; 发送移位寄存器空中断禁止
1 ]; w  W, S7 w, b, @, ~: ^& y    // ABDOVE disabled; 自动波特率采集中断禁止# G6 c& k% L! z" ?
    // CERIE disabled; 校验和错误中断禁止
3 x0 O& p8 F) d5 R4 v6 a2 \% c5 ~8 c    // CERIF disabled;检验和错误中断标志清除1 Y/ {% y! K4 p! X1 G7 |+ C5 G
    // PERIE disabled;  奇偶校验错误中断标志清除2 U0 _+ Z7 |: A% P, t$ o
    U1STA = 0x00;
7 h+ v5 N1 B% @8 d; c' _    9 R' C7 _) ~- D0 [5 k) e
    // URXISEL RX_ONE_WORD; 在缓冲区有1个以上字节时触发接收中断
  @& J) `1 C; b    // UTXBE enabled; 发送缓冲区设为空,在UTXEN=0时写入1将复位TX FIFO指针和计数器
' f+ {7 K5 P3 U# T$ z* X   
4 C+ C- d; q0 D' B2 v5 o  v    // UTXISEL TX_BUF_EMPTY; 发送缓冲区全空时触发中断" ?! M+ @7 X0 s: w( \! `  x
   
& P& Y6 \/ e6 O6 ^3 v1 d, W9 m    // URXBE enabled; 接收缓冲区为空,在URXEN=1时写入1将复位RX FIFO指针和计数器
6 b# J. u# b1 c( J2 @+ [3 L    // STPMD disabled; 在第一个或第二个停止位(取决于STSEL)的中间位置触发RXIF( [4 g/ O" b4 S( `! N( v
    // TXWRE disabled; 清除写发送错误标志
# Q% Q: h% {+ _) ~. h( [9 \    U1STAH = 0x22;7 p% X( n% ~4 Z7 O( ]0 g( g
    - B. u& l2 v0 w' O/ e. g
        // BaudRate = 38400; Frequency = 4,000,000 Hz; BRG 25; . q  q4 P: t/ `* ^5 p  d- j

2 W1 ^: ^0 W( c4 }6 g    U1BRG =0x19;" \3 J% M3 |2 c& N
    U1BRGH = 0x00;
% A* S! s( k  s3 D8 C* I7 r+ ^   
1 f4 C. p' V  ]% {! u8 `9 A3 {4 R    U1P1 = 0x00;
/ `0 m' G, W( h( a# p# J3 \4 D    U1P2 = 0x00;  R; ~3 `& o* c+ }4 t
    U1P3 = 0x00;
* Y8 i7 _0 j3 u, F" Q9 [! H) k, ^    U1P3H = 0x00;& E  V6 ~4 m( \2 k; C
    U1TXCHK = 0x00;
; t6 n1 i3 v: I- T    U1RXCHK = 0x00;' h1 A0 ^& W& p0 E5 X
   
8 D) G1 z- P. k/ a    U1SCCON = 0x00;//
6 X7 }# J! O+ v0 x    % G; C- {4 H9 u5 Y4 I
    U1SCINT = 0x00;
  H. p* Y& \0 G- a& e   
" W8 Y5 }! j8 v    // UART1中断寄存器  |# B  a' T# Q2 y
    // ABDIF disabled; ABAUD 未使能,或已使能但未完成自动波特率, ~7 y" @6 [9 R7 ~& j7 D
    // WUIF disabled; WAKE 未使能,或已使能但未发生唤醒事件9 l) B6 ~6 T7 x9 ?
    // ABDIE disabled; 不设置事件中断
. {. {+ k! p$ W    U1INT = 0x00;6 J5 k/ j$ k  U, J1 d. \

7 z8 ?2 F7 G8 u0 F/ c
- x. {8 B3 `# r) {6 i! h' a    IEC0bits.U1RXIE = 1;// UART1接收中断允许4 V2 b9 @+ X6 p7 I0 k
   
4 c: x4 v  j5 S* X% A# U  
6 T% A# ], A- I7 m& N}2 y! |% y$ V% ?3 a. y0 v

2 p* P$ \; J% R7 O/ A
: q/ |3 o( I4 K4 C" L7 e* Q
8 ~3 H' i( Z+ y9 m$ s
! O6 X$ n. N$ h; \; c5 e' D各种办法都试过了,包括降低波特率,提高优先级,关闭了所有其他中断,把TX发送中断改为7个空位,等等,都试过了。甚至只发送chr(04) &“197331”,结果收到的还是chr(4) &“197332”。改为不用DMA都没有问题,有没有大侠能够指点一下) ?5 @% z  j) r% ^( o2 T" J

该用户从未签到

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

该用户从未签到

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

该用户从未签到

4#
发表于 2022-12-2 13:34 | 只看该作者
可能是由什么冲突,把其他中断都关了。
9 S8 x: {& M3 I; `9 c再有别的DMA,关掉,有竞争,都关了。  c* \9 H( U. Q' n* i! |4 `
是不是变量或者BUF定义有问题。: [2 R. N# s' A6 L2 T
不行就改用发送中断直接处理了!

该用户从未签到

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

本版积分规则

关闭

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

EDA365公众号

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

GMT+8, 2025-11-6 03:05 , Processed in 0.156250 second(s), 23 queries , Gzip On.

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

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

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