|
|
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
|
|