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

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

[复制链接]

该用户从未签到

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

EDA365欢迎您登录!

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

x
用DMA0向UART1-TX发数据,出现奇怪现象,要发送的字节提前了,而且总数还是对的?
8 Y! y9 J, G1 X+ L要发送的数据为2 Y( b" d6 i( c2 ]6 M$ ^
chr(04) & 197331" & chr(0x1B) & "2021Echo00202111”
4 y: p& [( C5 a接收到的是:" F! S/ S$ S/ R* p
chr(04) & 197332"& chr(0x1B) & "202EEch2**202**- W7 T. @5 `  H  r: |; U

% u. {7 O8 i# q, e8 i1 w8 X1 g5 v5 m3 e/ Z
经过试验发现197332最后一个2,是2021第一个2多发一遍,并且覆盖了前面的1
4 A4 a9 T: H' Z0 e3 u
3 T! o) W& n! L; g: n6 f6 y; z% h' g
DMA设置:
! G% g. t1 s% U* X  j* ?static void SendCC(uint8_t ComName)
, ]# i" K- J8 z{& ?( f! c! _- @9 I% c
    uint8_t i ;; A2 Z2 A% U+ }/ R. S% m

* E3 c$ Z0 I% N- h; ?0 r        //- ********本段为DMA为初始化部分***********/& M! U  B1 ~9 `# Y( z  K! ?- f$ ]4 m

! ?) a/ d8 q8 R8 H9 ]' ?( F    DMACONbits.DMAEN = 0; //禁止DMA模块) H$ t- o% p- p3 b% ~
    DMACONbits.PRSSEL = 1;  //优先级循环方案
* |2 O5 q6 {9 N    DMAL = 0;                                                //RAM寻址下限  h6 O/ z8 S- a
        DMAH = 0x8000;                        //RAM寻址上限
' G6 j, m* o" l3 x) d7 D        IPC3bits.U1TXIP = 7;  //DMA0优先级为7& O( s/ ?. K; `
        
+ j9 q' S8 l3 J( N0 y  w/ |        IEC0bits.DMA0IE = 0;   //关闭DMA0中断. }! W, C; F4 n
        IEC0bits.DMA1IE = 0;   //关闭DMA1中断
# b8 L& R1 J" b; s7 H/ g6 e. u        IEC1bits.DMA2IE = 0;   //关闭DMA2中断
& D, T- E9 @7 T) I        IEC1bits.DMA3IE = 0;   //关闭DMA3中断/ \  L3 L* f5 C1 u
//禁用计时器中断矢量
% x% S8 s1 i% d' s$ O& L6 H            T1CONbits.TON = 0;      
( {2 C& R9 X9 r0 }( j            _T1IE = 0;
! y' N9 P$ F8 h$ A" I) W- @                IEC0bits.INT0IE = 0;
" p+ a4 J% v) C0 Z. U% z  e, V/ b2 e2 z0 z0 ?/ n2 ?- V$ }' }8 y
        //- ********************************************
2 @) O3 E0 u2 i3 \$ @+ M5 w9 i+ k- w5 I
  //-------初始化DMA0-------------------( `. V' v4 Q+ h+ o! v& T9 o$ N9 M
    // ******设置DMA0通道从COMM_BUF向UART1-FIFO发送数据*****************
2 J! c* L+ }# r- d        DMACH0 = 0x42;                        //禁止DMA0,并开始对DMA进行配置        " z# Y- j& B( ?
        DMASRC0 = (unsigned short int) & Send_Comm_Buf + 4 ;//设置DMA0的源数据地址; Y( z, @5 v$ E& M+ R6 f1 S$ B  [  B  F
        //                DMASRC0 = *Send_Comm_Buf;//设置DMA0的原数据地址
* n9 E" U, y1 `! z- _) h        DMADST0 = (unsigned short int) & U1TXREG;//设置DMA0目标地址为UART1-FIFO;
* d9 }& C2 M" {6 j8 l% Q  u    DMAINT0bits.CHSEL = 0x05;//设置DMA0通道触发源为UART1' u3 S5 y4 }* C
    DMAINT0bits.HALFEN = 1;        //设置DMA0半满中断
  V8 ~2 a8 e* n: [) f. H7 z) x
' L) {, F; b' f8 I( i( T4 d; J8 @) I7 W$ ~- O$ }
  //-------------------------------------( }1 V6 e* b6 J. L, B8 `1 Y; j

0 h& j/ P) \9 A) E) f //写入前7个字节,即指令号+器件ID,
- x: F7 V( q- r( | //由于器件ID为6字节,由于某些通讯部件FIFO不支持7个字节的存入,须将器件字节分段1 R8 s! n/ G1 J* I5 `
//现分为两段,即直接写入FIFO的,包含指令一共4个字节
' a4 K4 Q. b5 n) Y& p: [7 \7 _, z) A; I. ]% m3 L  n0 z
        Send_Comm_Buf_P = Send_Comm_Buf;
& d& b) o; Q, }0 p: ^, X. K    U1TXREG =  ComName ;//写入指令) L) u4 ]# S  }1 s# N
        *Send_Comm_Buf_P++ = ComName;//指令写入Buf,Buf指针加一& J, u  s+ g: m# i
        for (i=0;i<6;i++)6 D$ z" m+ N. c2 {) G
    {$ o) S! ?# t  O" ]: f  b1 c7 B
        *Send_Comm_Buf_P++ = SYSID;//写入数据到Buf
" v  k& r0 _9 U  p        if (i<=2)
8 k; l3 e* X0 g0 s8 Q! Q# I  @1 ~        {# S: |; j, X' R9 U, h, M" z
                  U1TXREG = SYSID ;//写入数据到FIFO: t$ V; L1 H+ ?, M1 k
        }
' ~% M, a  {0 o+ F, O# I    }
0 u) `; J, Y0 i6 {  D3 L8 l/ v' B8 h" A3 N; j! L* r
3 c$ V$ ]3 r' T" u0 B6 u

/ ?, o$ O+ C+ C8 d9 D        // 以下针对各不同指令进行处理,不再直接写入TXBUF,而由DMA进行处理
6 E! x# E5 K- Q5 o( e  i        //  发送本机基本参数,
5 f7 w) R- U8 `7 j& H% n        if (ComName == C_SysInf)6 y; e' P+ n( F' x1 b
        {8 i( ?% D* I3 R
                        Send_Comm_Buf_Len = 0x1B;9 M, j% ?6 }# p8 L2 A- T1 z0 w
4 {5 {- K0 P( E" t; B+ c; T
                        *Send_Comm_Buf_P++ = Send_Comm_Buf_Len;//07:指令长度3 d3 [$ Z1 E, I1 d. r
                        *Send_Comm_Buf_P++ = SYSMData[0];//08:出厂日期Y
5 w" g9 f* m. G: ~5 T0 Y! G1 G                        *Send_Comm_Buf_P++ = SYSMData[1];//09:        Y
. W# Q( f( {3 I1 T9 }" A& ^4 D                        *Send_Comm_Buf_P++ = SYSMData[2];//0A        M% t1 G/ ?/ H% ?
                        *Send_Comm_Buf_P++ = SYSMData[3];//0B        D
4 M! x% D3 A; d$ a! d                        *Send_Comm_Buf_P++ = SYSModel[0];//0C型号
' M, h) z+ x! L0 `                        *Send_Comm_Buf_P++ = SYSModel[1];//0D型号
' |4 l; I9 H( B) B& m  L                        *Send_Comm_Buf_P++ = SYSModel[2];//0F型号7 q0 S5 S, H0 r/ j; I# N  c
                        *Send_Comm_Buf_P++ = SYSModel[3];//10型号
% i9 J" b- A# p+ `- |2 G) u                        *Send_Comm_Buf_P++ = SYSMEdition[0];//11出厂版本号
; R9 R; ^% w0 n& F                        *Send_Comm_Buf_P++ = SYSMEdition[1];//12
1 r$ }3 W# }3 C3 i* P+ d" y) P                        *Send_Comm_Buf_P++ = SYSCData[0];//13系统更新日期Y
; d' D( n9 d3 K6 F: a& |' a. S  t, r                        *Send_Comm_Buf_P++ = SYSCData[1];//14            Y
7 n) w- Z$ ]6 K: e9 ?2 q                        *Send_Comm_Buf_P++ = SYSCData[2];//15            M* }! H' ?# M$ k( W; u5 L# C2 y1 N
                        *Send_Comm_Buf_P++ = SYSCData[3];//16            D: M# z; W. O8 k& q
                        *Send_Comm_Buf_P++ = SYSCEdition[0];//17更新的版本号
2 q$ m/ ~6 I4 {                        *Send_Comm_Buf_P++ = SYSCEdition[1];//18; ^4 D6 Z+ f# }8 o$ E# K, P8 C6 g1 b
        }+ }0 J9 q( P, n! k' ^
        
" _( Q' s5 w  r# p        //启动通讯-DMA; @4 p( N: P0 {1 N; }% A# K
% d5 L" T7 X9 p% {
        DMACNT0 = Send_Comm_Buf_Len - 7;  //设置传输数据数量
3 T# y8 }7 B, v; r' Z9 N        U1STAHbits.UTXISEL = 0;//TX接收缓冲区有8个空位触发中断
* H/ \# M' e5 f; _* v4 N        // *********************************************************************' Y; m+ W; L, y+ J
        
$ A/ j& I% v( y2 X! P& V        // **************启动DMA0***************************************
" n: c# r2 x2 _        //IFS0bits.DMA0IF = 0;   //清除DMA0中断标志
6 J1 `7 s0 C% X" p! j        DMACONbits.DMAEN = 1 ;  //启动DMA模块
  a  i# K4 X, J5 P4 ~        DMACH0bits.CHEN = 1;        //使能DMA0
* m- }) c6 O8 j7 }$ \- o/ F         
; v- N; ~2 Z% q! R% K& a% y        // ************************************************************- g7 ~' g, C! t1 c& L
        
4 R( n6 Z1 y1 i4 s        IEC0bits.U1TXIE = 1;//开启U1中断, x3 f$ x) {+ p( `2 k/ U- `2 K
        IEC0bits.DMA0IE = 1;   //开启DMA中断! h8 k6 u) x; [8 l% z0 \2 q
        
' o$ n9 F% e5 ~4 A. U' _) I        6 C6 {/ a/ {  Z

- H, c! c* S" B+ q' L}* O% P5 \) R% ^
, a6 r' T% \  h. d
UART设置:" D' x+ [+ P8 Z, d

3 N. X2 _3 ^( ~+ F" I
/ P- N% h8 d  r( x/ o6 x* O9 V, a( X7 q1 o; E

/ K* Z/ O( D) y3 V# Ivoid UART1_Initialize(void)2 K- M3 ^6 \  I' @, l4 j
{1 u+ g* o( S) @, m, M$ X
    // URXEN disabled; URXEN禁用;4 a" Q" S- i; R& H3 q* f- o
    // RXBIMD RXBKIF flag when Break makes low-to-high transition after being low for at least 23/11 bit periods;
8 t" e4 u6 h5 b    // RXBIMD RXBKIF 标志当中断在低到高过渡至少23/11位期间后进行低到高转换;
+ w" b7 F0 h% v( q    // UARTEN enabled;使能Uart1;
- q+ J7 B4 N0 @4 x: J    // MOD Asynchronous 8-bit UART; 异步8位UART;
" k, v+ n# F2 `* @; k0 B    // UTXBRK disabled; 禁止同步暂停符号发送0 Y% i' j/ \3 R
    // BRKOVR TX line driven by shifter;  TX线由移位器驱动;
8 x: K; s: ?" m" t8 m; j  i    // UTXEN disabled; 禁止发送;5 p$ H! d- ~. |! a# a8 }
    // USIDL disabled; 在空闲模式下工作;% {- D. U2 R* u+ V6 z; W
    // WAKE disabled; 关闭唤醒使能1 i5 u7 n* C4 P; m& s& p
    // ABAUD disabled; 禁止自动波特率检测
& X! F6 r; @! C( J2 b& J    // BRGH enabled; 高速波特率(baudclk/4), r, S5 \( L0 h2 z4 k- I6 O. [
      U1MODE = (0x8080 & ~(1<<15));  // disabling UARTEN bit% ]3 t6 l& d: Z. ~% l$ z
  / [4 X" v  R0 U. d4 f
    // STSEL 1 Stop bit sent; 一个停止位; o# y6 l$ y; N# W, |& x2 x
    // 1 checked at RX; * y# ~3 ?3 Z" {( J% a# M
    // BCLKMOD disabled; 使用传统技术器生成波特率具体取决于BRGH位;) \) \0 S4 ?2 s* F8 T
    // SLPEN disabled; 休眠模式下关闭
" h; Q7 m1 C& ]9 ?! U1 C0 D    // FLO Off;流控制关闭
( n% B% F$ O9 p( G, C8 i/ g: C4 ?    // BCLKSEL FOSC/2; 时钟源为Fosc/2(指令周期时钟)$ _4 J1 B- Z& U$ l4 x
    // C0EN disabled; 校验和模式05 ^' L6 q. X" w. a/ K0 s, y
    // RUNOVF disabled;检测到溢出错误时RX停止接受新数据
8 R" _  j' T+ q* X( O- `    // UTXINV disabled; 输出数据不翻转,空闲状态TX高电平; v  F( W' D6 k& E) T7 |" A
    // URXINV disabled; 输入数据不翻转,空闲状态为高电平4 x; R" H4 K8 R1 O" o% B9 Y6 ^
    // HALFDPLX disabled; 全双工模式
5 b2 V; w3 A) W3 W9 C& t- x    U1MODEH = 0x00;
1 K3 B; r% Q0 v, h: D4 m    6 V2 a% e7 D8 d1 R; ]4 c
    // OERIE disabled; 接收缓冲区溢出中断禁止  N1 q' C% O. G, n$ l
    // RXBKIF disabled; 接收暂停字符中断禁止5 w' z0 a/ g+ e7 i# V) @' ]. L2 N
    // RXBKIE disabled; 接收暂停字符中断标志位清除/ s1 S# }7 d; [3 y7 F  r
    // ABDOVF disabled; BRG尚未在自动波特率采集序列期间计满返回
+ E3 M8 x* ~) ?5 w4 M1 \    // OERR disabled; 接收缓冲区溢出标志清除9 Q* Q/ o: i9 Z3 {: Z3 y3 o
    // TXCIE disabled; 发送冲突中断禁止$ t$ m8 U; E  _' s; y1 L+ y" _
    // TXCIF disabled; 发送冲突中断标志清除
! e5 D! q) `- x    // FERIE disabled; 帧错误中断禁止
$ [# t! Q: Q- r- m/ B6 R/ Z    // TXMTIE disabled; 发送移位寄存器空中断禁止" ~5 H3 T$ r0 k9 C$ ?
    // ABDOVE disabled; 自动波特率采集中断禁止( t" x! H/ [9 z' ?, X1 N$ I: D
    // CERIE disabled; 校验和错误中断禁止
+ H# x5 a$ X  r6 u- j$ H# h    // CERIF disabled;检验和错误中断标志清除" s  r3 B! ]. r, I+ ^
    // PERIE disabled;  奇偶校验错误中断标志清除, W* c7 q, s% o: a1 q+ h  A, [8 y, \
    U1STA = 0x00;
0 y6 z- C) M. Z9 q% _0 N    ' ^& k. \3 K* _$ H
    // URXISEL RX_ONE_WORD; 在缓冲区有1个以上字节时触发接收中断
# P. t  M' v8 R    // UTXBE enabled; 发送缓冲区设为空,在UTXEN=0时写入1将复位TX FIFO指针和计数器
  e- Q0 s( V- ~3 _- z- V  A   
! Q6 G+ |/ t$ t, z+ |$ {1 U; z- s    // UTXISEL TX_BUF_EMPTY; 发送缓冲区全空时触发中断2 _8 b4 Q- b, f6 C
   
. Y8 ~# m; y- b$ h' P    // URXBE enabled; 接收缓冲区为空,在URXEN=1时写入1将复位RX FIFO指针和计数器
& p' \4 O+ `/ s+ @. T: x    // STPMD disabled; 在第一个或第二个停止位(取决于STSEL)的中间位置触发RXIF4 Z% Q" I. W) x/ {4 e
    // TXWRE disabled; 清除写发送错误标志) E/ }; L; L. m
    U1STAH = 0x22;& y/ z+ A% e& j
    2 |$ b" t5 U7 a! G
        // BaudRate = 38400; Frequency = 4,000,000 Hz; BRG 25;
% Z( r7 ?9 x' N" U* g/ a8 P* h) t9 [
    U1BRG =0x19;9 ]! F# I" X3 y+ @# w0 q3 a
    U1BRGH = 0x00;; {! ]# p0 g7 ]) }: y9 B1 C
   
; z! U9 `; [; }: ?! x    U1P1 = 0x00;
1 O+ H$ i9 T" v% h: |    U1P2 = 0x00;  e0 Z& R( i* Z
    U1P3 = 0x00;4 g$ a& M3 W- s5 B5 h1 D
    U1P3H = 0x00;
+ m- @- {6 c/ I( E3 R2 I* O4 }    U1TXCHK = 0x00;
% j8 K+ H/ o! B: B$ Z; U) {7 a9 [    U1RXCHK = 0x00;" a2 k8 @8 L# H/ v- @9 G4 K
   
& }) l2 W1 A! V3 t/ @$ i, `  \    U1SCCON = 0x00;//
8 ?7 X, m) U5 [" D4 c! m9 T' a   
; k' f9 `; z: c% e8 A! ]    U1SCINT = 0x00;
' _* F+ P9 ^7 a( Y/ ~* o4 T   
( Z1 [4 |% H: s8 Y3 G% G1 B- Q    // UART1中断寄存器
, N& U/ B* h! ~& q    // ABDIF disabled; ABAUD 未使能,或已使能但未完成自动波特率
* |5 Q  Q8 @' g    // WUIF disabled; WAKE 未使能,或已使能但未发生唤醒事件! f) G* m! d6 p
    // ABDIE disabled; 不设置事件中断
# g; \/ m' \! X, o: B% x5 b    U1INT = 0x00;
7 ~3 y, u# m' r! G+ @$ q. e- n( I  o5 U# o5 A. C
7 ?0 {" u: t6 i9 V
    IEC0bits.U1RXIE = 1;// UART1接收中断允许( s) v1 t6 E: r( h' k+ w
   
: p' I- a- W4 @  
. ^0 f8 y5 N- o8 e$ K8 d" a' c}
; r2 h0 ~! ?+ Q* f& I/ ~9 |0 \1 G2 s! u3 T

( Z* I9 J9 V! Y$ P$ c6 c5 E* S& L' `8 z
* Q3 u8 X* b: \8 q8 W: }6 `- P; D3 _2 i' w  q! ]( F; s. A
各种办法都试过了,包括降低波特率,提高优先级,关闭了所有其他中断,把TX发送中断改为7个空位,等等,都试过了。甚至只发送chr(04) &“197331”,结果收到的还是chr(4) &“197332”。改为不用DMA都没有问题,有没有大侠能够指点一下6 U: ], a9 ~3 N# x# C- ^

该用户从未签到

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

该用户从未签到

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

该用户从未签到

4#
发表于 2022-12-2 13:34 | 只看该作者
可能是由什么冲突,把其他中断都关了。
2 N- a; o) W0 i再有别的DMA,关掉,有竞争,都关了。
" a% O" h9 ?' I2 a: h6 D是不是变量或者BUF定义有问题。
7 C8 e3 m# R8 ^6 Z1 e* j不行就改用发送中断直接处理了!

该用户从未签到

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

本版积分规则

关闭

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

EDA365公众号

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

GMT+8, 2025-8-2 13:33 , Processed in 0.125000 second(s), 23 queries , Gzip On.

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

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

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