|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
用DMA0向UART1-TX发数据,出现奇怪现象,要发送的字节提前了,而且总数还是对的?
) Y" V8 ^% l2 g1 Z- B0 n' K要发送的数据为, B0 a3 i- |3 L
chr(04) & 197331" & chr(0x1B) & "2021Echo00202111”
% K1 q. L% d: b, e接收到的是:4 ]8 D# }7 t. \& g
chr(04) & 197332"& chr(0x1B) & "202EEch2**202**- K( ?* L$ |& y+ C
0 u: B) s1 Y1 K& Y
- [( c. K- K& m1 h1 k
经过试验发现197332最后一个2,是2021第一个2多发一遍,并且覆盖了前面的1, @5 L' b3 p) f: E9 m
9 O2 S0 ?6 L) o0 V: @4 A$ T
) i m; R% \5 H4 F
DMA设置:
2 N( w p9 Y, x1 Estatic void SendCC(uint8_t ComName)- X9 |. |8 ?8 H5 D$ b+ ~1 P
{3 l, d# V4 J+ E: m0 v" b
uint8_t i ;
4 q- d: L/ @ ~# s( s+ P0 e' J3 B4 m( i7 j; Y! x( E4 ^2 O" s
//- ********本段为DMA为初始化部分***********/
8 K; H2 C3 X5 y6 ^
4 f4 I2 z/ ^' V0 A DMACONbits.DMAEN = 0; //禁止DMA模块
" m5 b$ v: I; a DMACONbits.PRSSEL = 1; //优先级循环方案4 Z: B$ q& f$ J6 s) G: V
DMAL = 0; //RAM寻址下限/ Y8 i- _! j( Z! L5 H ^
DMAH = 0x8000; //RAM寻址上限& \, a$ H3 g& n2 s8 |: }9 E8 R: I- A
IPC3bits.U1TXIP = 7; //DMA0优先级为7) d8 M9 O: J' c
9 s$ U- _0 \2 q4 ] IEC0bits.DMA0IE = 0; //关闭DMA0中断
3 {, G8 r; {4 [8 P3 z IEC0bits.DMA1IE = 0; //关闭DMA1中断7 a& j+ J S( d ~
IEC1bits.DMA2IE = 0; //关闭DMA2中断" W. g. _& Y) V" M6 k
IEC1bits.DMA3IE = 0; //关闭DMA3中断
& x! R. n. v7 ]5 j1 G" D//禁用计时器中断矢量
& r4 T( |" F- t! J T1CONbits.TON = 0;
& }8 [ D; k3 ^1 u2 p _T1IE = 0;/ S& w6 ~# y0 E! F' @2 q
IEC0bits.INT0IE = 0;8 l' I' C* m" @) ?( ]2 Z
+ `8 a9 |3 F5 l! Y8 o Z- Z8 h //- ********************************************( k) h! f$ T; G6 T& A' ^% q
$ j: q" @& _& o$ b //-------初始化DMA0-------------------/ d2 Q8 K) D( `0 P5 C
// ******设置DMA0通道从COMM_BUF向UART1-FIFO发送数据*****************6 ?9 G( j( V- ?2 |
DMACH0 = 0x42; //禁止DMA0,并开始对DMA进行配置 . U! q- ^7 j$ `1 Y1 w
DMASRC0 = (unsigned short int) & Send_Comm_Buf + 4 ;//设置DMA0的源数据地址$ b+ G, K4 B# i
// DMASRC0 = *Send_Comm_Buf;//设置DMA0的原数据地址
' J2 Z# u0 F! r M5 ` DMADST0 = (unsigned short int) & U1TXREG;//设置DMA0目标地址为UART1-FIFO;
* }8 R3 s: v' Y7 h3 A u+ u DMAINT0bits.CHSEL = 0x05;//设置DMA0通道触发源为UART18 r) \, W; @ O w9 z) U
DMAINT0bits.HALFEN = 1; //设置DMA0半满中断! w! c) Q% F8 N2 @( A
+ S/ k; d. U; a6 E. m4 m
+ b/ w8 y3 w) j) b! D5 z# o% c
//-------------------------------------2 @* J4 L4 q+ S; C8 O: J2 N T
( V0 P, h( D+ S6 p0 H
//写入前7个字节,即指令号+器件ID,
! k- ^! x/ q8 l4 U1 F! H //由于器件ID为6字节,由于某些通讯部件FIFO不支持7个字节的存入,须将器件字节分段
4 i2 N; v. X. ?, X //现分为两段,即直接写入FIFO的,包含指令一共4个字节
* I+ S" L: _, a, C7 O6 M4 Y' N ~0 j7 e. ?
Send_Comm_Buf_P = Send_Comm_Buf;
. Q7 ~- Z n# C! h5 u0 {% f U1TXREG = ComName ;//写入指令
" c. ]8 e7 j8 N1 X- k. n8 u$ ~1 f6 K *Send_Comm_Buf_P++ = ComName;//指令写入Buf,Buf指针加一
8 {) l0 B4 Y( b, l. D for (i=0;i<6;i++)
" F7 O3 V* M4 _/ q {) k! V) n' |0 l* G" i
*Send_Comm_Buf_P++ = SYSID;//写入数据到Buf5 t+ h3 G4 Q3 T# C: `; a( [
if (i<=2)
# i+ L! c/ h2 R* i, K3 A4 T! Y4 H5 |. B {
! k7 C& f/ U+ {6 a U1TXREG = SYSID ;//写入数据到FIFO
! \2 Y2 A4 y, R }
1 t4 ?8 O/ Q' O0 A) i' z" x }
: O# O r& v+ z& t" Q" a
# T: y9 p8 f, ?7 l+ P7 ?+ @+ L" ?1 O) Z( S7 r9 c: N# I1 X7 \
1 X! v; [% A3 W$ I. }# g8 Z7 D
// 以下针对各不同指令进行处理,不再直接写入TXBUF,而由DMA进行处理, d- u: X* f7 h+ K$ ^. w0 `7 w
// 发送本机基本参数,
D& c/ w3 W1 F2 l/ [8 e0 y6 o if (ComName == C_SysInf): q7 J/ A# w* |5 L6 T* x8 m
{
$ o. H3 |9 J( M' p9 s- b+ U; {9 d8 }, n Send_Comm_Buf_Len = 0x1B;
5 |" d% D% d- f
* X. |3 j! j) c! l3 r *Send_Comm_Buf_P++ = Send_Comm_Buf_Len;//07:指令长度& F9 c0 x3 @6 l4 L8 }% a
*Send_Comm_Buf_P++ = SYSMData[0];//08:出厂日期Y
1 s |3 F7 \: M0 y) m *Send_Comm_Buf_P++ = SYSMData[1];//09: Y
5 [2 v; V! H" V# P8 u2 F *Send_Comm_Buf_P++ = SYSMData[2];//0A M4 S( _) R( u R+ Q* D. R7 e
*Send_Comm_Buf_P++ = SYSMData[3];//0B D
! P& C; s( @2 V' W, v/ h *Send_Comm_Buf_P++ = SYSModel[0];//0C型号; x8 D2 s% P1 X9 F* P7 j6 P D
*Send_Comm_Buf_P++ = SYSModel[1];//0D型号1 Z0 ^& E" ]! L# `1 k
*Send_Comm_Buf_P++ = SYSModel[2];//0F型号' t$ f2 y, W- e+ P; t! y
*Send_Comm_Buf_P++ = SYSModel[3];//10型号) b1 {# u( |% D" k0 a/ l& k
*Send_Comm_Buf_P++ = SYSMEdition[0];//11出厂版本号
; P2 i( ]3 R) _7 ^ o *Send_Comm_Buf_P++ = SYSMEdition[1];//12
1 l# F9 _' U' Q0 r. l *Send_Comm_Buf_P++ = SYSCData[0];//13系统更新日期Y
5 G6 [* m7 n' V: M. j- b9 H% K *Send_Comm_Buf_P++ = SYSCData[1];//14 Y3 x5 K7 I9 ]5 r! c' t
*Send_Comm_Buf_P++ = SYSCData[2];//15 M* w+ x& n& B6 y6 ?
*Send_Comm_Buf_P++ = SYSCData[3];//16 D8 G# j y5 [) y' L2 `) r+ x, J& w
*Send_Comm_Buf_P++ = SYSCEdition[0];//17更新的版本号
: M W! `- @ r( \0 ~ *Send_Comm_Buf_P++ = SYSCEdition[1];//18
# c7 s7 [( ]; v! n' m \5 q6 j }
- `! w3 G- }# r9 H) C/ Z& x% [% T7 b9 U
+ N$ y% V( U% {: h/ `& y //启动通讯-DMA6 ^# ?7 J9 k% V- w+ ]7 m2 n4 c& q
+ U% h! y2 d) C. s; J9 S, T
DMACNT0 = Send_Comm_Buf_Len - 7; //设置传输数据数量0 T8 O( J9 G: c$ @( [# }# ^& `, n
U1STAHbits.UTXISEL = 0;//TX接收缓冲区有8个空位触发中断# |) O# s" M8 }0 I6 y9 x4 p
// *********************************************************************( D/ f* o- _" c
3 m3 w7 H6 p5 q* t! i; g/ v1 |3 R9 m
// **************启动DMA0***************************************6 P0 m) a3 Y8 J6 N- [1 e, I# p
//IFS0bits.DMA0IF = 0; //清除DMA0中断标志9 U" M. A \# v# j( s8 A
DMACONbits.DMAEN = 1 ; //启动DMA模块
% d7 [1 [' v, S' l! v& R DMACH0bits.CHEN = 1; //使能DMA0/ C5 X( o* S/ a9 S) D: K% M# K K5 k
" U2 D6 J6 p, u" H* J
// ************************************************************4 ?7 W) g. o& T+ D {' D4 e) H
; a; q2 C9 r5 b; F$ M
IEC0bits.U1TXIE = 1;//开启U1中断
& {6 y/ n' B+ s' X1 ~( Q& O6 ^ IEC0bits.DMA0IE = 1; //开启DMA中断0 H. ?: I- Z5 |- S N
* W4 }1 T2 Y& C/ u# Z : f" ~% e# Q ~ v4 Y" F
& O; B; Z! w1 W3 }4 y}
3 T; O& S" l: d& F' Z
$ U k f9 v$ @5 H; uUART设置:: U4 y/ f% y2 T. @# S4 J
" L! q! e W1 z! p& g* m1 I
/ n& ]( f! J" L6 M* r/ c! F
! J) A0 }. l" E" {! g$ B
, _. X! y, A/ T$ ?void UART1_Initialize(void)
, y0 Q) T1 P# ^; W4 ~9 D{
' \* q; l& a% Y1 ~: \& F( M: p1 F // URXEN disabled; URXEN禁用;
/ U P# `4 J/ ^ // RXBIMD RXBKIF flag when Break makes low-to-high transition after being low for at least 23/11 bit periods;
8 c8 ]4 g$ c! T0 T) q+ h' a. }2 v; [ // RXBIMD RXBKIF 标志当中断在低到高过渡至少23/11位期间后进行低到高转换;" Q4 v8 T1 ^% s* @, E4 [
// UARTEN enabled;使能Uart1;
2 N/ ]( R0 ]5 i! c: w& b- r8 m( S // MOD Asynchronous 8-bit UART; 异步8位UART;) N9 N6 S* V3 Z6 n; M
// UTXBRK disabled; 禁止同步暂停符号发送
4 J, ~6 N' x0 n8 v* _ // BRKOVR TX line driven by shifter; TX线由移位器驱动;6 n; o% R' G, U% Q
// UTXEN disabled; 禁止发送; o# B# _& C) O P3 n x0 |
// USIDL disabled; 在空闲模式下工作;
1 D+ |# q) D& v // WAKE disabled; 关闭唤醒使能
, o1 z' ^- }0 ~' [& B3 L8 W // ABAUD disabled; 禁止自动波特率检测
( z& K( b9 V$ x // BRGH enabled; 高速波特率(baudclk/4)
/ Z! H4 x& [" l6 ?% G4 S# A U1MODE = (0x8080 & ~(1<<15)); // disabling UARTEN bit
( K3 k4 z, T/ k# W/ X& q+ B
" ?; I+ g8 C8 ~$ \1 R // STSEL 1 Stop bit sent; 一个停止位0 o! {% c. r; Z/ l* }5 l+ [
// 1 checked at RX; ! ]! z ^- X. ?1 [3 F: W- l
// BCLKMOD disabled; 使用传统技术器生成波特率具体取决于BRGH位;
; T( X9 S, I: B // SLPEN disabled; 休眠模式下关闭( {( B% ^6 Q$ a0 {# i
// FLO Off;流控制关闭
8 P3 [* ~0 O. Q) X5 |$ z. D // BCLKSEL FOSC/2; 时钟源为Fosc/2(指令周期时钟)9 P$ j5 x: T2 {1 }
// C0EN disabled; 校验和模式0* k: C7 Y5 x7 b
// RUNOVF disabled;检测到溢出错误时RX停止接受新数据
$ ]2 {) H" w% T4 M3 W // UTXINV disabled; 输出数据不翻转,空闲状态TX高电平
4 B( S9 }# v7 |$ l O6 r // URXINV disabled; 输入数据不翻转,空闲状态为高电平$ F! W X$ O8 b
// HALFDPLX disabled; 全双工模式& u# r. @% k, P1 G0 q
U1MODEH = 0x00;
; Z$ O7 k& _! Z& @ ; _. h& E0 y; S
// OERIE disabled; 接收缓冲区溢出中断禁止$ F1 ]5 I5 Z: C, E* z' W' I& ?
// RXBKIF disabled; 接收暂停字符中断禁止; K, u' P, u- c1 Y: s5 U
// RXBKIE disabled; 接收暂停字符中断标志位清除" M+ C! C- b3 [% k4 ?2 h
// ABDOVF disabled; BRG尚未在自动波特率采集序列期间计满返回) I) c% s- c |( D) z
// OERR disabled; 接收缓冲区溢出标志清除
! j# w+ M- u" @) y% a7 A- z // TXCIE disabled; 发送冲突中断禁止
4 z8 C- s# w" ?- `) @ // TXCIF disabled; 发送冲突中断标志清除( n! Y$ l# Q% O+ Y$ P& y: \6 a1 r
// FERIE disabled; 帧错误中断禁止
9 z3 o' B; O5 h' Z4 J+ G0 S // TXMTIE disabled; 发送移位寄存器空中断禁止* W0 ^ o7 U* h
// ABDOVE disabled; 自动波特率采集中断禁止
) X0 g6 Q* @' D2 Z1 Y& J // CERIE disabled; 校验和错误中断禁止
0 w+ a' C2 Z$ ~9 q3 s2 V# b // CERIF disabled;检验和错误中断标志清除
, e- d! k8 S( e // PERIE disabled; 奇偶校验错误中断标志清除
/ p3 G, L( d; ~" N U1STA = 0x00;" d4 F! V' M# p, ]1 {# ^% b
8 v0 {. t8 l( [4 V) e! R! N9 T) J
// URXISEL RX_ONE_WORD; 在缓冲区有1个以上字节时触发接收中断
6 `. n2 O! m J6 G7 U // UTXBE enabled; 发送缓冲区设为空,在UTXEN=0时写入1将复位TX FIFO指针和计数器
: i5 S1 q3 g- e3 F' e " `. V& M3 w) Z+ ]; z* {8 L" b4 K, n0 _
// UTXISEL TX_BUF_EMPTY; 发送缓冲区全空时触发中断: x# E8 C8 u- f/ B9 w7 ]& z- \
" D: ^: t, G g- v+ S" T
// URXBE enabled; 接收缓冲区为空,在URXEN=1时写入1将复位RX FIFO指针和计数器9 h) m8 s% O5 g# N$ f$ b
// STPMD disabled; 在第一个或第二个停止位(取决于STSEL)的中间位置触发RXIF
, U9 O/ G1 v0 K' D // TXWRE disabled; 清除写发送错误标志& ]; D6 ~, U1 W" \' r
U1STAH = 0x22;5 M) R; B% ?: V5 o5 a( P6 L% ?
9 C1 e: @" n v: f3 Z Y! K // BaudRate = 38400; Frequency = 4,000,000 Hz; BRG 25; 8 _9 L( f5 O2 ?
) |' z/ Z* U( H U1BRG =0x19;( Y# P; A- I" V8 @7 e
U1BRGH = 0x00;5 d) [% i- r6 c# n$ Z' O* s
, H {" @" w+ P& H: ^, V6 t! b U1P1 = 0x00;
+ D7 A! ^* o2 `! L; t) x U1P2 = 0x00;1 V& {/ a7 p% n! a8 r3 r4 y
U1P3 = 0x00;/ ?' E5 C N* @* s
U1P3H = 0x00;4 p: F' j, {4 k/ X1 j
U1TXCHK = 0x00;' q5 }6 @, }$ _1 c h! _
U1RXCHK = 0x00;$ {! O+ |, ^3 B/ c3 K
' [" [$ f3 z# u U1SCCON = 0x00;//+ b1 d) ]+ z- c" ~
1 I% P# j/ j) Q2 ?3 G: K U1SCINT = 0x00;
9 \. e! ~: S ^4 D- {0 [6 R : X8 A& ^* j7 H+ v8 H
// UART1中断寄存器" l: d* ~+ O/ W7 H3 T! R' A" W
// ABDIF disabled; ABAUD 未使能,或已使能但未完成自动波特率
5 I7 i/ x: t% M+ F* u) y1 A5 P // WUIF disabled; WAKE 未使能,或已使能但未发生唤醒事件
. B! I) H u. O8 B% \6 u // ABDIE disabled; 不设置事件中断
) H( Y7 f, I" t4 O& N, n U1INT = 0x00;% C! M, Q6 _: M E, T4 R9 D, B3 |2 ^6 a
1 `- h. q/ H& l8 {2 t# @) Y7 _6 C+ W+ z
+ ]! W: L" X- q X$ G. E IEC0bits.U1RXIE = 1;// UART1接收中断允许+ ?7 p7 n0 `% _5 x- z) D
& [5 t( W" Q( n" }
$ ?4 ]! y1 S* T0 M/ C* ^}5 s4 @) s5 ?" ?$ |' n6 _$ y6 B
0 l! {$ L% T3 |9 I' K; C5 n& P! u# }9 [6 @& k l9 U2 Q
) x- d% `& y* C! E. z% J5 `
) r8 [) Q' S+ b x( C! g
各种办法都试过了,包括降低波特率,提高优先级,关闭了所有其他中断,把TX发送中断改为7个空位,等等,都试过了。甚至只发送chr(04) &“197331”,结果收到的还是chr(4) &“197332”。改为不用DMA都没有问题,有没有大侠能够指点一下
1 w5 a0 p7 o. J0 i* J |
|