久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 5390|回復: 10
打印 上一主題 下一主題
收起左側

STC12單片機的串口1和2為何傳輸質量差別很遠?

[復制鏈接]
跳轉到指定樓層
樓主
這是我這新年寫的單片機串口通訊程序,必須兩個串口能同時收也同時發,比如1收后再從1輸出,也向2輸出,2收后再從2輸出,也向1輸出,用串口助s手以1MS間隔自動向單片機發送,并接收回來的字串,實驗結果是:

1. 串口1收后向串口1發送,并向串口2發送,從9600-115200,運行一小時都不會有亂碼。

2. 串口2收后向串口1發送,從9600-115200,一點都沒問題。
3. 串口2收后向串口2發送,接收幾百到幾千byte后就會死機,有時兩個byte就死機,換了各種頻率的晶振,嘗試各種速率,都無法解決問題。

由于無法知道死機的位置,于是用T0寫了個流水燈觀察,發現死機后流水燈還會動,表示程序沒有跑飛,幾番實驗,終于確定是死在對busybit(41H)的檢測,把這條檢測 “JB 41H, CHECKBUSY2"去掉就不再死機,但每接收到幾百個byte就會有遺失一兩個字符,懷疑是速率太快,但降到19200也是如此,上網查了一下沒什么資料,看說明書也沒提到這些,只好來請教各位前輩了,問題如下:

1. 為何串口2的S2TI,S2RI都不能位尋址,設定手續麻煩,是否因此影響到串口2的通訊質量。
2. 有沒有其他單片機有比較好的串口(能位尋址)。

我接下來需要做有四個串口的板,串口搞不好就只能作罷了。





;THIS IS FOR UART TEST

FIRSTBUFFER EQU 80H
LASTBUFFER EQU 0FFH
BRT EQU 09CH
;------------THIS FOR PCON.7=0 256-X=A
;247(11.0592, 38400) 253(11.0592 115200) 245(11.0592 MIDI 31.4) 238(19200) 220(9600)
;251(18.4320 115200) 241(18.432 38400) 226(18.432, 19200) 196(18.432, 9600)
;250(22.1184 115200) 238(22.1184, 38400)
;229(33.1776. 38400) 247(33.1776, 115200) 202(33.1776,19200) 148(33.1776, 9600)
;------------THIS FOR PCON.7=1
;250(3.6864, 38400) 249(3.6864 32U MIDI)
;226(18.432, 38400) 219(18.4320, 2USx16=32U MIDI)
;238(11.0592, 38400) 250(11.0592, 115200) 220(11.0592, 19200) 184(11.0592, 9600) 234(11.0592, 31250 MIDI 2USx16=32US)
;202(33.1776. 38400) 193?(33.1776, 31250 MIDI) 238(33.1776, 115200) 148(33.1776,19200) 40(33.1776, 9600)

BRTLOAD EQU 251
RELOAD_COUNT EQU 251 ;(18.4320M)

S2CON EQU 9AH     ;S2SM0, S2SM1, S2SM2, S2REN, S2TB8, S2RB8, S2TI, S2RI
IE2 EQU 0AFH      ;X, X, X, X, X, X, ESPI, ES2
IP2 EQU 0B5H      ;X,X,X,X,X,X,PSPS,PS2 PSPI=PARITY OF SPI
S2BUF EQU 9BH
LEDTIME EQU 4

AUXR EQU 8EH
AUXR1 EQU 0A2H        ;7,6=PCA-P4,5=SPI-P4,4=S2-P4,3=GF2,2=ADRJ,1,0=DPS
WAKE_CLKO EQU 08FH    ;WAKEUP AND CLOCK OUTPUT CONTROL REGISTER

ORG 0000H
LJMP MAIN
ORG 0003H
LJMP EXT_INT0 ;EXTERNAL INTERRUPT0
ORG 000BH
LJMP TIMER_0  ;TIMER0 INTERRUPT
ORG 0013H
LJMP EXT_INT1 ;EXTERNAL INTERRUPT1
ORG 001BH
LJMP TIMER_1 ;TIMER1 INTERRUPT
ORG 0023H
LJMP UART1    ;UART1 RECEIVED INTERRUPT
ORG 002BH
LJMP ADC      ;T2
ORG 0033H
LJMP LVD
ORG 003BH
LJMP PCA
ORG 0043H
LJMP UART2   ;UART2 RECEIVED INTERRUPT
ORG 004BH
LJMP SPI
ORG 0100H

MAIN:
MOV 75H, #00000001B         ;FOR BIT ROTATE
MOV 3CH, #LEDTIME

MOV R0, #FIRSTBUFFER        ;INIT THE BTYE TO SENT IN BUFFER POINTER
MOV R1, #FIRSTBUFFER        ;INIT THE POINTER FOR BYTE CAN STORE IN BUFFER
MOV WAKE_CLKO,#00000000B    ;ENABLE BRT(=4),T1(=2) T0(=1) HAVE CLOCK OUTPUT BRT@P1.0 T1@P3.5 T0@P3.4
MOV AUXR,#01000100B         ;T0X12,T1X12,UART_M0X6,BRTRUN, ;S2SMOD,BRTX12,EXTRAM, S1BRS(1=UART1 USE BRT 0=USE T1)
MOV TMOD, #00100001B        ;TIMER1 AS 8 BITS RELOAD, TIMER_0 AS MOD 1

LCALL INITIAL_UART1         ;USE BRT AS SERIAL BAUD GENERATE FOR UART1 AS RECEIVED DATA FROM FRONT RECEIVER
LCALL INITIAL_UART2         ;USE BRT AS SERIAL BAUD GENERATE FOR UART2
SETB EA                    ;ENAABLE ALL INTERRUPT
SETB ET0                    ;SWITCH ON T0 INTERRUPT
SETB TR0                    ;RUN TIMER-0

LED:     
DJNZ 3AH, LED1 ;THIS IS FOR LEDSHOWDELAY
DJNZ 3BH, LED1
DJNZ 3CH, LED1
CPL P1.5       ;INDICATE LED LIGHTUP
MOV 3CH, #LEDTIME
LED1:
MOV A, R0
XRL A, R1
JZ LEDEXIT
MOV A, @R0
LCALL SENTONEBYTE1
MOV A, @R0
LCALL SENTONEBYTE2
LCALL NEXTBUFFER0
LEDEXIT:
JMP LED

NEXTBUFFER0:
CJNE R0, #LASTBUFFER, NEXTBUFFER0A
MOV R0, #FIRSTBUFFER
JMP NEXTBUFFER0EXIT
NEXTBUFFER0A:
INC R0  ;POINT TO NEXT BYTE
NEXTBUFFER0EXIT:
RET

INITIAL_UART1:         
MOV SCON, #01010000B   ;SET AS BAUD VERIABLE, NO ODD/EVEN CHECK
MOV TH1, #RELOAD_COUNT        
MOV TL1, #RELOAD_COUNT
SETB PS                         ;SERIAL PORT PRORITY HIGH
SETB TR1                        ;RUN TIMER_1
SETB ES                         ;ENABLE UART1 INTERRUPT
RET

UART1:      
;/*----------------------------
;UART1 INTERRUPT SERVICE ROUTINE
;----------------------------*/
PUSH ACC
PUSH PSW
JNB RI, UART1CHECKTI
CLR RI
MOV A, SBUF                  ;READ THE CHARACTER FROM THE SERIAL PORT
MOV @R1, A
CJNE R1, #LASTBUFFER, NEXTBUFFER1
MOV R1, #FIRSTBUFFER
JMP UART1EXIT
NEXTBUFFER1:
INC R1                       ;POINT TO NEXT BUFFER
JMP UART1EXIT
UART1CHECKTI:
CLR TI
CLR 40H ;NOT BUSY
UART1EXIT:
POP PSW
POP ACC
RETI

SENTONEBYTE1:                ;SENT OUT A
CHECKBUSY1:
JB 40H, CHECKBUSY1
SETB 40H
MOV SBUF, A
RET

INITIAL_UART2:         
MOV S2CON, #01010000B  ;SET AS BAUD VERIABLE, NO ODD/EVEN CHECK
MOV BRT, #BRTLOAD      ;RELOAD
ORL AUXR, #10H         ;BRT START RUN
MOV IP2, #01H          ;UART INTERUUPT PARITY HIGH
MOV IE2, #01H          ;ENABLE UART2 INTERRUPT
RET

UART2:                ;THIS RECEIVED DATA AND STORE TO BUFFER FOR SENT OUT
;/*----------------------------
;UART2 INTERRUPT SERVICE ROUTINE
;----------------------------*/
PUSH ACC
PUSH PSW
MOV  A, S2CON                ;READ UART2 CONTROL REGISTER
ANL A, #00000001B            ;ANL, IF S2RI=0 THEN 0
JZ UART2CHECKTI
MOV A, S2BUF
MOV @R1, A
MOV A, S2CON                 ;READ UART2 CONTROL REGISTER AGAIN
ANL A, #11111110B            ;CLEAR S2RI BIT
MOV S2CON, A                 ;SAVE BACK S2CON
CJNE R1, #LASTBUFFER, NEXTBUFFER2
MOV R1, #FIRSTBUFFER
JMP UART2EXIT
NEXTBUFFER2:
INC R1                       ;POINT TO NEXT BUFFER
JMP UART2EXIT
UART2CHECKTI:                ;NOT USE
MOV A, S2CON                 ;READ UART2 CONTROL REGISTER AGAIN
ANL A, #11111101B            ;CLEAR S2TI BIT
MOV S2CON, A
CLR 41H
CLR 41H
UART2EXIT:
POP    PSW
POP    ACC
RETI

SENTONEBYTE2:        ;SENT OUT DATA IN A
CHECKBUSY2:
JB 41H, CHECKBUSY2
SETB 41H
MOV S2BUF, A
RET

EXT_INT0:            ;IF P3.2 H2L COME HERE SET TIMER, ONLY FIRST H2L WILL ACT
RETI

TIMER_0:             ;USE FOR GENERATE SYS-CLOCK
PUSH ACC
MOV A, 75H
MOV P0, A
RL A
MOV 75H, A
MOV P2, S2CON
MOV TH0, #0      
MOV TL0, #0
POP ACC
RETI

EXT_INT1:        ;USE FOR INFRA RED
RETI
TIMER_1:
RETI
ADC:
RETI
PCA:
RETI
LVD:
RETI
SPI:
RETI


END

uart2-TEST.jpg (82.04 KB, 下載次數: 31)

uart2-TEST.jpg
分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏2 分享淘帖 頂 踩
回復

使用道具 舉報

沙發
ID:432823 發表于 2019-2-8 14:55 | 只看該作者
串口通訊口2的中斷優級較低,這一點要注意。
回復

使用道具 舉報

板凳
ID:371423 發表于 2019-2-8 17:17 | 只看該作者
我曾經用15系列的同時開定時器0、1,ADC、串口1、3的中斷。結果串口3,兩個字節之間延時達到毫秒才能無漏掉地接收,估計是中斷優先級太低的問題。
回復

使用道具 舉報

地板
ID:155507 發表于 2019-2-8 20:51 | 只看該作者

我給你來個程序試試
STC8A8K64S4A12 單片機的一個4串口同時中斷收發的程序,4個全雙工串口工作于不同的波特率,115200,57600,38400,19200,然后你可以接4臺電腦的串口助手,同時測試,程序會數據原樣返回,你可以每個串口測試1M字節看看,沒有問題的。
  1. /*********************************************************/
  2. #define MAIN_Fosc  24000000L        //定義主時鐘

  3. #include "STC8xxxx.H"


  4. /*************        功能說明        **************

  5. 4串口全雙工中斷方式收發通訊程序。

  6. 通過PC向MCU發送數據, MCU收到后通過串口把收到的數據原樣返回.

  7. 默認參數:
  8. 所有設置均為 1位起始位, 8位數據位, 1位停止位, 無校驗.
  9. 每個串口可以使用不同的波特率.
  10. 串口1(P3.0 P3.1): 115200bps.
  11. 串口2(P1.0 P1.1):  57600bps.
  12. 串口3(P0.0 P0.1):  38400bps.
  13. 串口4(P0.2 P0.3):  19200bps.


  14. ******************************************/

  15. /*************        本地常量聲明        **************/
  16. #define        RX1_Length        128                /* 接收緩沖長度 */
  17. #define        RX2_Length        128                /* 接收緩沖長度 */
  18. #define        RX3_Length        128                /* 接收緩沖長度 */
  19. #define        RX4_Length        128                /* 接收緩沖長度 */

  20. #define        UART_BaudRate1        115200UL         /* 波特率 */
  21. #define        UART_BaudRate2         57600UL         /* 波特率 */
  22. #define        UART_BaudRate3         38400UL         /* 波特率 */
  23. #define        UART_BaudRate4         19200UL         /* 波特率 */


  24. /*************        本地變量聲明        **************/
  25. u8        xdata        RX1_Buffer[RX1_Length];        //接收緩沖
  26. u8        xdata        RX2_Buffer[RX2_Length];        //接收緩沖
  27. u8        xdata        RX3_Buffer[RX3_Length];        //接收緩沖
  28. u8        xdata        RX4_Buffer[RX4_Length];        //接收緩沖

  29. u8        TX1_read,RX1_write;        //讀寫索引(指針).
  30. u8        TX2_read,RX2_write;        //讀寫索引(指針).
  31. u8        TX3_read,RX3_write;        //讀寫索引(指針).
  32. u8        TX4_read,RX4_write;        //讀寫索引(指針).

  33. bit        B_TX1_Busy,B_TX2_Busy,B_TX3_Busy,B_TX4_Busy;        // 發送忙標志


  34. /*************        本地函數聲明        **************/
  35. void        UART1_config(u8 brt);        // 選擇波特率, 2: 使用Timer2做波特率, 其它值: 使用Timer1做波特率.
  36. void        UART2_config(u8 brt);        // 選擇波特率, 2: 使用Timer2做波特率, 其它值: 無效.
  37. void        UART3_config(u8 brt);        // 選擇波特率, 2: 使用Timer2做波特率, 其它值: 使用Timer3做波特率.
  38. void        UART4_config(u8 brt);        // 選擇波特率, 2: 使用Timer2做波特率, 其它值: 使用Timer4做波特率.
  39. void         PrintString1(u8 *puts);
  40. void         PrintString2(u8 *puts);
  41. void         PrintString3(u8 *puts);
  42. void         PrintString4(u8 *puts);




  43. //========================================================================
  44. // 函數: void main(void)
  45. // 描述: 主函數
  46. // 參數: none.
  47. // 返回: none.
  48. // 版本: VER1.0
  49. // 日期: 2016-4-28
  50. // 備注:
  51. //========================================================================
  52. void main(void)
  53. {
  54.         EAXRAM();

  55.         UART1_config(1);        // 選擇波特率, 2: 使用Timer2做波特率, 其它值: 使用Timer1做波特率.
  56.         UART2_config(2);        // 選擇波特率, 2: 使用Timer2做波特率, 其它值: 無效.
  57.         UART3_config(3);        // 選擇波特率, 2: 使用Timer2做波特率, 其它值: 使用Timer3做波特率.
  58.         UART4_config(4);        // 選擇波特率, 2: 使用Timer2做波特率, 其它值: 使用Timer4做波特率.
  59.        
  60.         EA = 1;

  61.         PrintString1("STC8 serial USART1 Test Prgramme!\r\n");
  62.         PrintString2("STC8 serial USART2 Test Prgramme!\r\n");
  63.         PrintString3("STC8 serial USART3 Test Prgramme!\r\n");
  64.         PrintString4("STC8 serial USART4 Test Prgramme!\r\n");


  65.         while (1)
  66.         {

  67.                 if((TX1_read != RX1_write) && !B_TX1_Busy)        //收到過數據, 并且發送空閑
  68.                 {
  69.                         B_TX1_Busy = 1;                //標志發送忙
  70.                         SBUF = RX1_Buffer[TX1_read];        //發一個字節
  71.                         if(++TX1_read >= RX1_Length)        TX1_read = 0;        //避免溢出處理
  72.                 }

  73.                 if((TX2_read != RX2_write) && !B_TX2_Busy)        //收到過數據, 并且發送空閑
  74.                 {
  75.                         B_TX2_Busy = 1;                //標志發送忙
  76.                         S2BUF = RX2_Buffer[TX2_read];        //發一個字節
  77.                         if(++TX2_read >= RX2_Length)        TX2_read = 0;        //避免溢出處理
  78.                 }

  79.                 if((TX3_read != RX3_write) && !B_TX3_Busy)        //收到過數據, 并且發送空閑
  80.                 {
  81.                         B_TX3_Busy = 1;                //標志發送忙
  82.                         S3BUF = RX3_Buffer[TX3_read];        //發一個字節
  83.                         if(++TX3_read >= RX3_Length)        TX3_read = 0;        //避免溢出處理
  84.                 }

  85.                 if((TX4_read != RX4_write) && !B_TX4_Busy)        //收到過數據, 并且發送空閑
  86.                 {
  87.                         B_TX4_Busy = 1;                //標志發送忙
  88.                         S4BUF = RX4_Buffer[TX4_read];        //發一個字節
  89.                         if(++TX4_read >= RX4_Length)        TX4_read = 0;        //避免溢出處理
  90.                 }
  91.         }
  92. }


  93. //========================================================================
  94. // 函數: SetTimer2Baudraye(u16 dat)
  95. // 描述: 設置Timer2做波特率發生器。
  96. // 參數: dat: Timer2的重裝值.
  97. // 返回: none.
  98. // 版本: VER1.0
  99. // 日期: 2016-4-28
  100. // 備注:
  101. //========================================================================
  102. void        SetTimer2Baudraye(u16 dat)        // 選擇波特率, 2: 使用Timer2做波特率, 其它值: 使用Timer1做波特率.
  103. {
  104.         AUXR &= ~(1<<4);        //Timer stop
  105.         AUXR &= ~(1<<3);        //Timer2 set As Timer
  106.         AUXR |=  (1<<2);        //Timer2 set as 1T mode
  107.         T2H = dat / 256;
  108.         T2L = dat % 256;
  109.         IE2  &= ~(1<<2);        //禁止中斷
  110.         AUXR |=  (1<<4);        //Timer run enable
  111. }


  112. //========================================================================
  113. // 函數: void        UART1_config(u8 brt)
  114. // 描述: UART1初始化函數。
  115. // 參數: brt: 選擇波特率, 2: 使用Timer2做波特率, 其它值: 使用Timer1做波特率.
  116. // 返回: none.
  117. // 版本: VER1.0
  118. // 日期: 2016-4-28
  119. // 備注:
  120. //========================================================================
  121. void        UART1_config(u8 brt)        // 選擇波特率, 2: 使用Timer2做波特率, 其它值: 使用Timer1做波特率.
  122. {
  123.         u8        i;
  124.         /*********** 波特率使用定時器2 *****************/
  125.         if(brt == 2)
  126.         {
  127.                 AUXR |= 0x01;                //S1 BRT Use Timer2;
  128.                 SetTimer2Baudraye(65536UL - (MAIN_Fosc / 4) / UART_BaudRate1);
  129.         }

  130.         /*********** 波特率使用定時器1 *****************/
  131.         else
  132.         {
  133.                 TR1 = 0;
  134.                 AUXR &= ~0x01;                //S1 BRT Use Timer1;
  135.                 AUXR |=  (1<<6);        //Timer1 set as 1T mode
  136.                 TMOD &= ~(1<<6);        //Timer1 set As Timer
  137.                 TMOD &= ~0x30;                //Timer1_16bitAutoReload;
  138.                 TH1 = (65536UL - (MAIN_Fosc / 4) / UART_BaudRate1) / 256;
  139.                 TL1 = (65536UL - (MAIN_Fosc / 4) / UART_BaudRate1) % 256;
  140.                 ET1 = 0;        //禁止中斷
  141.                 //        INT_CLKO &= ~0x02;        //不輸出時鐘
  142.                 INT_CLKO |=  0x02;        //  輸出時鐘
  143.                 TR1  = 1;
  144.         }
  145.         /*************************************************/

  146.         SCON = (SCON & 0x3f) | (1<<6);        // 8位數據, 1位起始位, 1位停止位, 無校驗
  147.         //        PS  = 1;        //高優先級中斷
  148.         ES  = 1;        //允許中斷
  149.         REN = 1;        //允許接收
  150.         P_SW1 = P_SW1 & 0x3f;                                P3n_push_pull(0x02);        //切換到 P3.0 P3.1
  151.         //        P_SW1 = (P_SW1 & 0x3f) | (1<<6);        P3n_push_pull(0x80);        //切換到P3.6 P3.7
  152.         //        P_SW1 = (P_SW1 & 0x3f) | (2<<6);        P1n_push_pull(0x80);        //切換到P1.6 P1.7 (必須使用內部時鐘)

  153.         for(i=0; i<RX1_Length; i++)                RX1_Buffer[i] = 0;
  154.         B_TX1_Busy  = 0;
  155.         TX1_read    = 0;
  156.         RX1_write   = 0;
  157. }


  158. //========================================================================
  159. // 函數: void        UART2_config(u8 brt)
  160. // 描述: UART2初始化函數。
  161. // 參數: brt: 選擇波特率, 2: 使用Timer2做波特率, 其它值: 無效.
  162. // 返回: none.
  163. // 版本: VER1.0
  164. // 日期: 2016-4-28
  165. // 備注:
  166. //========================================================================
  167. void        UART2_config(u8 brt)        // 選擇波特率, 2: 使用Timer2做波特率, 其它值: 無效.
  168. {
  169.         u8        i;
  170.         /*********** 波特率固定使用定時器2 *****************/
  171.         if(brt == 2)        SetTimer2Baudraye(65536UL - (MAIN_Fosc / 4) / UART_BaudRate2);

  172.         S2CON &= ~(1<<7);        // 8位數據, 1位起始位, 1位停止位, 無校驗
  173.         IE2   |= 1;                        //允許中斷
  174.         S2CON |= (1<<4);        //允許接收
  175.         P_SW2 &= ~1;        P1n_push_pull(0x02);        //切換到 P1.0 P1.1
  176.         //        P_SW2 |= 1;                P4n_push_pull(0x80);        //切換到 P4.6 P4.7

  177.         for(i=0; i<RX2_Length; i++)                RX2_Buffer[i] = 0;
  178.         B_TX2_Busy  = 0;
  179.         TX2_read    = 0;
  180.         RX2_write   = 0;
  181. }

  182. //========================================================================
  183. // 函數: void        UART3_config(u8 brt)
  184. // 描述: UART3初始化函數。
  185. // 參數: brt: 選擇波特率, 2: 使用Timer2做波特率, 其它值: 使用Timer3做波特率.
  186. // 返回: none.
  187. // 版本: VER1.0
  188. // 日期: 2016-4-28
  189. // 備注:
  190. //========================================================================
  191. void        UART3_config(u8 brt)        // 選擇波特率, 2: 使用Timer2做波特率, 其它值: 使用Timer3做波特率.
  192. {
  193.         u8        i;
  194.         /*********** 波特率固定使用定時器2 *****************/
  195.         if(brt == 2)
  196.         {
  197.                 S3CON &= ~(1<<6);        //BRT select Timer2
  198.                 SetTimer2Baudraye(65536UL - (MAIN_Fosc / 4) / UART_BaudRate3);
  199.         }
  200.         /*********** 波特率使用定時器3 *****************/
  201.         else
  202.         {
  203.                 S3CON |= (1<<6);        //BRT select Timer3
  204.                 T4T3M &= 0xf0;                //停止計數, 清除控制位
  205.                 IE2  &= ~(1<<5);        //禁止中斷
  206.                 T4T3M |=  (1<<1);        //1T
  207.                 T4T3M &= ~(1<<2);        //定時
  208.                 T4T3M &= ~1;                //不輸出時鐘
  209.                 T3H = (65536UL - (MAIN_Fosc / 4) / UART_BaudRate3) / 256;
  210.                 T3L = (65536UL - (MAIN_Fosc / 4) / UART_BaudRate3) % 256;
  211.                 T4T3M |=  (1<<3);        //開始運行
  212.         }
  213.        
  214.         S3CON &= ~(1<<5);        //禁止多機通訊方式
  215.         S3CON &= ~(1<<7);        // 8位數據, 1位起始位, 1位停止位, 無校驗
  216.         IE2   |=  (1<<3);        //允許中斷
  217.         S3CON |=  (1<<4);        //允許接收
  218.         P_SW2 &= ~2;        P0n_push_pull(0x02);        //切換到 P0.0 P0.1
  219.         //        P_SW2 |= 2;                P5n_push_pull(0x02);        //切換到 P5.0 P5.1

  220.         for(i=0; i<RX3_Length; i++)                RX3_Buffer[i] = 0;
  221.         B_TX3_Busy  = 0;
  222.         TX3_read    = 0;
  223.         RX3_write   = 0;
  224. }

  225. //========================================================================
  226. // 函數: void        UART4_config(u8 brt)
  227. // 描述: UART4初始化函數。
  228. // 參數: brt: 選擇波特率, 2: 使用Timer2做波特率, 其它值: 使用Timer4做波特率.
  229. // 返回: none.
  230. // 版本: VER1.0
  231. // 日期: 2016-4-28
  232. // 備注:
  233. //========================================================================
  234. void        UART4_config(u8 brt)        // 選擇波特率, 2: 使用Timer2做波特率, 其它值: 使用Timer4做波特率.
  235. {
  236.         u8        i;
  237.         /*********** 波特率固定使用定時器2 *****************/
  238.         if(brt == 2)
  239.         {
  240.                 S4CON &= ~(1<<6);        //BRT select Timer2
  241.                 SetTimer2Baudraye(65536UL - (MAIN_Fosc / 4) / UART_BaudRate4);
  242.         }
  243.         /*********** 波特率使用定時器3 *****************/
  244.         else
  245.         {
  246.                 S4CON |= (1<<6);        //BRT select Timer4
  247.                 T4T3M &= 0x0f;                //停止計數, 清除控制位
  248.                 IE2   &= ~(1<<6);        //禁止中斷
  249.                 T4T3M |=  (1<<5);        //1T
  250.                 T4T3M &= ~(1<<6);        //定時
  251.                 T4T3M &= ~(1<<4);        //不輸出時鐘
  252.                 T4H = (65536UL - (MAIN_Fosc / 4) / UART_BaudRate4) / 256;
  253.                 T4L = (65536UL - (MAIN_Fosc / 4) / UART_BaudRate4) % 256;
  254.                 T4T3M |=  (1<<7);        //開始運行
  255.         }
  256.        
  257.         S4CON &= ~(1<<5);        //禁止多機通訊方式
  258.         S4CON &= ~(1<<7);        // 8位數據, 1位起始位, 1位停止位, 無校驗
  259.         IE2   |=  (1<<4);        //允許中斷
  260.         S4CON |=  (1<<4);        //允許接收
  261.         P_SW2 &= ~4;        P0n_push_pull(0x08);        //切換到 P0.2 P0.3
  262.         //        P_SW2 |= 4;                P5n_push_pull(0x08);        //切換到 P5.2 P5.3

  263.         for(i=0; i<RX4_Length; i++)                RX4_Buffer[i] = 0;
  264.         B_TX4_Busy  = 0;
  265.         TX4_read    = 0;
  266.         RX4_write   = 0;
  267. }


  268. //========================================================================
  269. // 函數: void PrintString1(u8 *puts)
  270. // 描述: 串口1字符串打印函數
  271. // 參數: puts: 字符串指針.
  272. // 返回: none.
  273. // 版本: VER1.0
  274. // 日期: 2016-4-28
  275. // 備注:
  276. //========================================================================
  277. void PrintString1(u8 *puts)
  278. {
  279.         for (; *puts != 0;        puts++)
  280.         {
  281.                 B_TX1_Busy = 1;                //標志發送忙
  282.                 SBUF = *puts;                //發一個字節
  283.                 while(B_TX1_Busy);        //等待發送完成
  284.         }
  285. }

  286. //========================================================================
  287. // 函數: void PrintString2(u8 *puts)
  288. // 描述: 串口2字符串打印函數
  289. // 參數: puts: 字符串指針.
  290. // 返回: none.
  291. // 版本: VER1.0
  292. // 日期: 2016-4-28
  293. // 備注:
  294. //========================================================================
  295. void PrintString2(u8 *puts)
  296. {
  297.         for (; *puts != 0;        puts++)
  298.         {
  299.                 B_TX2_Busy = 1;                //標志發送忙
  300.                 S2BUF = *puts;                //發一個字節
  301.                 while(B_TX2_Busy);        //等待發送完成
  302.         }
  303. }

  304. //========================================================================
  305. // 函數: void PrintString3(u8 *puts)
  306. // 描述: 串口3字符串打印函數
  307. // 參數: puts: 字符串指針.
  308. // 返回: none.
  309. // 版本: VER1.0
  310. // 日期: 2016-4-28
  311. // 備注:
  312. //========================================================================
  313. void PrintString3(u8 *puts)
  314. {
  315.         for (; *puts != 0;        puts++)
  316.         {
  317.                 B_TX3_Busy = 1;                //標志發送忙
  318.                 S3BUF = *puts;                //發一個字節
  319.                 while(B_TX3_Busy);        //等待發送完成
  320.         }
  321. }

  322. //========================================================================
  323. // 函數: void PrintString4(u8 *puts)
  324. // 描述: 串口1字符串打印函數
  325. // 參數: puts: 字符串指針.
  326. // 返回: none.
  327. // 版本: VER1.0
  328. // 日期: 2016-4-28
  329. // 備注:
  330. //========================================================================
  331. void PrintString4(u8 *puts)
  332. {
  333.         for (; *puts != 0;        puts++)
  334.         {
  335.                 B_TX4_Busy = 1;                //標志發送忙
  336.                 S4BUF = *puts;                //發一個字節
  337.                 while(B_TX4_Busy);        //等待發送完成
  338.         }
  339. }



  340. //========================================================================
  341. // 函數: void UART1_int (void) interrupt UART1_VECTOR
  342. // 描述: 串口1中斷函數
  343. // 參數: none.
  344. // 返回: none.
  345. // 版本: VER1.0
  346. // 日期: 2016-4-28
  347. // 備注:
  348. //========================================================================
  349. void UART1_int (void) interrupt UART1_VECTOR
  350. {
  351.         if(RI)
  352.         {
  353.                 RI = 0;
  354.                 RX1_Buffer[RX1_write] = SBUF;
  355.                 if(++RX1_write >= RX1_Length)        RX1_write = 0;
  356.         }

  357.         if(TI)
  358.         {
  359.                 TI = 0;
  360.                 B_TX1_Busy = 0;
  361.         }
  362. }

  363. //========================================================================
  364. // 函數: void UART2_int (void) interrupt UART2_VECTOR
  365. // 描述: 串口2中斷函數
  366. // 參數: none.
  367. // 返回: none.
  368. // 版本: VER1.0
  369. // 日期: 2016-4-28
  370. // 備注:
  371. //========================================================================
  372. void UART2_int (void) interrupt UART2_VECTOR
  373. {
  374.         if(RI2)
  375.         {
  376.                 CLR_RI2();
  377.                 RX2_Buffer[RX2_write] = S2BUF;
  378.                 if(++RX2_write >= RX2_Length)        RX2_write = 0;
  379.         }

  380.         if(TI2)
  381.         {
  382.                 CLR_TI2();
  383.                 B_TX2_Busy = 0;
  384.         }

  385. }

  386. //========================================================================
  387. // 函數: void UART3_int (void) interrupt UART3_VECTOR
  388. // 描述: 串口3中斷函數
  389. // 參數: none.
  390. // 返回: none.
  391. // 版本: VER1.0
  392. // 日期: 2016-4-28
  393. // 備注:
  394. //========================================================================
  395. void UART3_int (void) interrupt UART3_VECTOR
  396. {
  397.         if(RI3)
  398.         {
  399.                 CLR_RI3();
  400.                 RX3_Buffer[RX3_write] = S3BUF;
  401.                 if(++RX3_write >= RX3_Length)        RX3_write = 0;
  402.         }

  403.         if(TI3)
  404.         {
  405.                 CLR_TI3();
  406.                 B_TX3_Busy = 0;
  407.         }

  408. }

  409. //========================================================================
  410. // 函數: void UART4_int (void) interrupt UART4_VECTOR
  411. // 描述: 串口4中斷函數
  412. // 參數: none.
  413. // 返回: none.
  414. // 版本: VER1.0
  415. // 日期: 2016-4-28
  416. // 備注:
  417. //========================================================================
  418. void UART4_int (void) interrupt UART4_VECTOR
  419. {
  420.         if(RI4)
  421.         {
  422.                 CLR_RI4();
  423.                 RX4_Buffer[RX4_write] = S4BUF;
  424.                 if(++RX4_write >= RX4_Length)        RX4_write = 0;
  425.         }

  426.         if(TI4)
  427.         {
  428.                 CLR_TI4();
  429.                 B_TX4_Busy = 0;
  430.         }

  431. }

復制代碼



STC8系列4個串口全雙工同時中斷收發測試例程.zip

17.15 KB, 下載次數: 22

評分

參與人數 2黑幣 +37 收起 理由
suuy79 + 2 贊一個!
dalaoshi + 35 很給力!

查看全部評分

回復

使用道具 舉報

5#
ID:47286 發表于 2019-2-8 22:55 | 只看該作者
再看看程序吧 我也用12c做了個東西 串口2和串口屏通訊 速率也是115200 一直沒事 用的就是官網給的范例
回復

使用道具 舉報

6#
ID:283954 發表于 2019-2-9 02:26 | 只看該作者
手頭還沒有STC8A的開發板,春節過后會買一個來試,我還沒有學C,但通過自己寫的程序,竟然也看懂C了,邏輯與我的匯編差不多,S2,S3,S4CON都不能位操作,所以都必須先讀進A進行and操作再存回,這期間如果剛好傳送完畢而SxTI置位,就會被寫回的SxCON覆蓋,無法產生中斷,因此SxBUSY位無法復位,這是我對這一問題的猜想,我今晚把uart1的RI和TI的重置方式改用與UART2的方式,就是讀入,AND,再寫回三部曲,結果問題就在UART1重現了,也許STC8有對UART進行一些改進也說不定。等試過就知。
回復

使用道具 舉報

7#
ID:283954 發表于 2019-2-15 12:40 | 只看該作者
dzbj 發表于 2019-2-8 22:55
再看看程序吧 我也用12c做了個東西 串口2和串口屏通訊 速率也是115200 一直沒事 用的就是官網給的范例

我也是一直用官網上的范例來用uart2,也沒問題,就是不滿足把一個BYTE放進SBUF后還要在那等發送完畢產生TI置位才可以走,那段時間全浪費了,這樣怎能做出高效的設計。這里網友提供的四個UART同時收發的例子才是正道,所以我開始造一個用STC8AXXXS4的板子來實驗。有了四個UART,如果同時收發效果不盡人意,就可以把收和發各自分配給不同的UART,避免意外死機。
回復

使用道具 舉報

8#
ID:283954 發表于 2019-2-15 12:53 | 只看該作者
yaoji123 發表于 2019-2-8 14:55
串口通訊口2的中斷優級較低,這一點要注意。

這個問題我也很困擾,后來也想通了,說明書上都說中斷發生后,不會被同級的中斷級別所打斷,但沒有強調這個后來的中斷是會被記住的,等當前的中斷結束后,就會被執行,所以這里有網友在勸告我們初哥不要在中斷程序里搞太多事,把資料移走后就趕快離開,因為在當前的中斷程序里呆太久,在那里等待處理的中斷又再產生同樣的中斷,就會遺失一個中斷,結果就是死機啦。
回復

使用道具 舉報

9#
ID:283954 發表于 2019-2-21 16:44 | 只看該作者
這問題最終也解決了,原來要把S2TI清除是可以直接用ANL指令的,只要一個指令:

ANL S2CON, #11111101B            ;CLEAR S2TI BIT

而不必先載入ACC, ANL之后再送回(三個指令):

MOV A, S2CON                             ;READ UART2 CONTROL REGISTER AGAIN
ANL S2CON, #11111101B            ;CLEAR S2TI BIT
MOV S2CON, A

又長知識了,實踐是邁向正確的最好辦法哈,現在那怕晶振頻率到了33M,115200BPS, 疲勞試驗幾小時也不出錯了。

謝謝各位前輩的指導。
回復

使用道具 舉報

10#
ID:283954 發表于 2019-5-5 23:50 | 只看該作者



終于買到STC8的板,可以進行四個串口的實驗了,C語言沒用過,只只能寫個匯編的,有了上次的經驗,這次寫的很順利,確定四個串口運作都很正常,但要同時開四個串口助手進行交叉實驗實在覺得累,只能這樣了。

;THIS FOR STC8 FOUR UART TESTING
;50H FOR UART1 WRITE POINTER
;51H FOR UART2 WRITE POINTER
;52H FOR UART3 WRITE POINTER
;53H FOR UART4 WRITE POINTER
;54H FOR UART1 READ POINTER
;55H FOR UART2 READ POINTER
;56H FOR UART3 READ POINTER
;57H FOR UART4 READ POINTER
;71H DELAY
;72H DELAY
;73H DELAY

;BIT
;40H FOR UART1 BUSY
;41H FOR UART2 BUSY
;42H FOR UART3 BUSY
;43H FOR UART4 BUSY

FIRSTBUFFER EQU 00H
LASTBUFFER EQU 0FFH
INTCLKO EQU 08FH   
IE2 EQU 0AFH           ;X, ET4, ET3, ES4, ES3, ET2, ESPI, ES2
S2CON EQU 9AH          ;S2SM0, S2SM1, S2SM2, S2REN, S2TB8, S2RB8, S2TI, S2RI
S3CON EQU 0ACH         ;SAME AS S2CON
S4CON EQU 84H
S2BUF EQU 9BH
S3BUF EQU 0ADH
S4BUF EQU 85H

T2H EQU 0D6H           
T2L EQU 0D7H  
P4 EQU 0C0H
P5 EQU 0C8H
P6 EQU 0E8H
P7 EQU 0F8H
AUXR EQU 8EH
AUXR2 EQU 08FH
AUXR1 EQU 0A2H

ORG 0000H
LJMP MAIN
ORG 0003H
LJMP EXT_INT0 ;EXTERNAL INTERRUPT0
ORG 000BH
LJMP TIMER_0  ;TIMER0 INTERRUPT
ORG 0013H
LJMP EXT_INT1 ;EXTERNAL INTERRUPT1
ORG 001BH
LJMP TIMER_1  ;TIMER1 INTERRUPT
ORG 0023H
LJMP UART1   
ORG 002BH
LJMP ADC      
ORG 0033H
LJMP LVD
ORG 003BH
LJMP PCA
ORG 0043H
LJMP UART2   
ORG 004BH
LJMP SPI
ORG 0053H
LJMP INT2
ORG 005BH
LJMP INT3
ORG 0063H
LJMP TIMER_2
ORG 0083H
LJMP INT4
ORG 008BH
LJMP UART3
ORG 0093H
LJMP UART4
ORG 009BH
LJMP TIMER_3
ORG 00A3H
LJMP TIMER_4
ORG 00ABH
LJMP CMP

MAIN:
MOV INTCLKO,#00000100B     ;ENABLE T2(=4),T1(=2) T0(=1) HAVE CLOCK OUTPUT T2@P1.3 T1@P3.5 T0@P3.4
MOV TMOD, #00000000B       ;TIMER_1 AS MOD0 (16BIT AUTO LOAD) ;TIMER_0 AS MOD0 MOD1=16BIT NOT AUTO LOAD
                           ;GATE, C/T,M1,M0(T1) GATE, C/T,M1,MO(T0)
MOV AUXR,#00010101B        ;T0x12,T1x12,UART_M0x6,T2RUN,T2C/T,T2x12,EXTRAM,S1ST2(UART1,0=T1 1=T2) ALL USE T2
MOV T2H, #0FFH             ;18.432 38400 12T=FFF6 1T=FF88 T2 RUN AS 16BIT AUTO LOAD
MOV T2L, #88H
SETB ES                    ;ENABLE UART1 INTERRUPT
MOV IE2, #00011001B        ;ENABLE UART4, UART3, UART2 INTERRUPT
LCALL INIT4UART            ;ALL USE TIMER2 AS BAUD RATE GENERATER
SETB EA                    ;ENABLE ALL INTERRUPT

LOOP:
CPL P1.7
;LCALL DELAY3
LCALL READ1
LCALL READ2
LCALL READ3
LCALL READ4
JMP LOOP


READ4:
MOV A, 53H
CJNE A, 58H, READ4A
JMP READ4EXIT
READ4A:
MOV DPH, #4
MOV DPL, 58H
MOVX A, @DPTR
INC 58H
MOV DPH, #0
LCALL SENTONEBYTE4
READ4EXIT:
RET

READ3:
MOV A, 52H
CJNE A, 57H, READ3A
JMP READ3EXIT
READ3A:
MOV DPH, #3
MOV DPL, 57H
MOVX A, @DPTR
INC 57H
MOV DPH, #0
LCALL SENTONEBYTE3
READ3EXIT:
RET


READ2:
MOV A, 51H
CJNE A, 56H, READ2A
JMP READ2EXIT
READ2A:
MOV DPH, #2
MOV DPL, 56H
MOVX A, @DPTR
INC 56H
MOV DPH, #0
LCALL SENTONEBYTE2
READ2EXIT:
RET

READ1:
MOV A, 50H
CJNE A, 55H, READ1A
JMP READ1EXIT
READ1A:
MOV DPH, #1
MOV DPL, 55H
MOVX A, @DPTR
INC 55H
MOV DPH, #0
LCALL SENTONEBYTE1
READ1EXIT:
RET

SENTONEBYTE1:                ;SENT OUT A
CHECKBUSY1:
JB 40H, CHECKBUSY1
SETB 40H
MOV SBUF, A
RET

SENTONEBYTE2:                ;SENT OUT DATA IN A
CHECKBUSY2:
JB 41H, CHECKBUSY2
SETB 41H
MOV S2BUF, A
RET

SENTONEBYTE3:                ;SENT OUT DATA IN A
CHECKBUSY3:
JB 42H, CHECKBUSY3
SETB 42H
MOV S3BUF, A
RET

SENTONEBYTE4:                ;SENT OUT DATA IN A
CHECKBUSY4:
JB 43H, CHECKBUSY4
SETB 43H
MOV S4BUF, A
RET

UART1:      
;/*----------------------------
;UART1 INTERRUPT SERVICE ROUTINE
;----------------------------*/
PUSH ACC
PUSH PSW
JNB RI, UART1CHECKTI
CLR RI
MOV A, SBUF                  ;READ THE CHARACTER FROM THE SERIAL PORT
MOV DPH, #1
MOV DPL, 50H
MOVX @DPTR, A
INC 50H                       ;POINT TO NEXT BUFFER
MOV DPH, #0
JMP UART1EXIT
UART1CHECKTI:
CLR TI
CLR 40H ;NOT BUSY
UART1EXIT:
POP PSW
POP ACC
RETI

UART2:  
;/*----------------------------
;UART2 INTERRUPT SERVICE ROUTINE
;----------------------------*/
PUSH ACC
PUSH PSW
MOV  A, S2CON                ;READ UART2 CONTROL REGISTER
ANL A, #00000001B            ;ANL, IF S2RI=0 THEN 0
JZ UART2CHECKTI
MOV A, S2BUF
MOV DPH, #2
MOV DPL, 51H
MOVX @DPTR, A
ANL S2CON, #11111110B         ;CLEAR S2RI BIT
INC 51H                       ;POINT TO NEXT BUFFER
MOV DPH, #0
JMP UART2EXIT
UART2CHECKTI:               
ANL S2CON, #11111101B        ;CLEAR S2TI BIT
CLR 41H
UART2EXIT:
POP    PSW
POP    ACC
RETI

UART3:  
;/*----------------------------
;UART3 INTERRUPT SERVICE ROUTINE
;----------------------------*/
PUSH ACC
PUSH PSW
MOV  A, S3CON                ;READ UART3 CONTROL REGISTER
ANL A, #00000001B            ;ANL, IF S3RI=0 THEN 0
JZ UART3CHECKTI
MOV A, S3BUF
MOV DPH, #3
MOV DPL, 52H
MOVX @DPTR, A
ANL S3CON, #11111110B        ;CLEAR S3RI BIT
INC 52H                      ;POINT TO NEXT BUFFER
MOV DPH, #0
JMP UART3EXIT
UART3CHECKTI:               
ANL S3CON, #11111101B        ;CLEAR S3TI BIT
CLR 42H
UART3EXIT:
POP    PSW
POP    ACC
RETI

UART4:  
;/*----------------------------
;UART4 INTERRUPT SERVICE ROUTINE
;----------------------------*/
PUSH ACC
PUSH PSW
MOV  A, S4CON                ;READ UART4 CONTROL REGISTER
ANL A, #00000001B            ;ANL, IF S4RI=0 THEN 0
JZ UART4CHECKTI
MOV A, S4BUF
MOV DPH, #4
MOV DPL, 53H
MOVX @DPTR, A
ANL S4CON, #11111110B        ;CLEAR S4RI BIT
INC 53H                      ;POINT TO NEXT BUFFER
MOV DPH, #0
JMP UART4EXIT
UART4CHECKTI:               
ANL S4CON, #11111101B        ;CLEAR S4TI BIT
CLR 43H
UART4EXIT:
POP    PSW
POP    ACC
RETI

DELAY3:
MOV 72H, #255
SLOWDOWN0:
MOV 71H, #125 ;255
SLOWDOWN:
MOV 73H, #11  ;11=18M
SLOWDOWN2:
DJNZ 73H, SLOWDOWN2
DJNZ 71H, SLOWDOWN
DJNZ 72H, SLOWDOWN0
RET

INIT4UART:  
MOV SCON, #01010000B     ;x,MOD1(NOT SAME AS UART1),x,RECEIVE ENABLE
MOV S2CON, #01010000B    ;MOD0,x,x,RECEIVE ENABLE
MOV S3CON, #00010000B    ;MOD0,0=USE T2,x,RECEIVE ENABLE
MOV S4CON, #00010000B    ;MOD0,0=USE T2,x,RECEIVE ENABLE
RET

EXT_INT0:
RETI
TIMER_0:
RETI
EXT_INT1:
RETI
TIMER_1:
RETI
;UART1:   
;RETI
ADC:      
RETI
LVD:
RETI
PCA:
RETI
;UART2:
;RETI
SPI:
RETI
INT2:
RETI
INT3:
RETI
TIMER_2:
RETI
INT4:
RETI
;UART3:
;RETI
;UART4:
;RETI
TIMER_3:
RETI
TIMER_4:
RETI
CMP:
RETI

END




回復

使用道具 舉報

11#
ID:55115 發表于 2019-5-31 10:15 | 只看該作者
剛下我需要下載來學習學習~
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規則

小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 日本精品视频一区二区 | 蜜臀网站| 91免费看片 | 日韩三 | 亚洲精品久久国产高清情趣图文 | 国产91精品久久久久久久网曝门 | a级大片免费观看 | 国产成人久久精品一区二区三区 | 请别相信他免费喜剧电影在线观看 | 日韩欧美三区 | 一区二区三区免费 | 久久久国产一区二区三区 | 午夜91| 99成人免费视频 | 成人一区二区视频 | 国产精品高潮呻吟久久 | 日本在线视频一区二区 | 久久久久久久久久久福利观看 | 久久久成人精品 | 成人午夜毛片 | 成人国产精品久久 | 91亚洲精品国偷拍自产在线观看 | 91夜色在线观看 | 中国一级大毛片 | 午夜影院在线观看免费 | 中文字幕 国产 | 久久99精品久久 | 免费在线观看成年人视频 | 婷婷狠狠 | 婷婷激情综合 | 亚洲人成网亚洲欧洲无码 | 婷婷久久综合 | 精品毛片| 国产成人精品999在线观看 | 亚洲在线中文字幕 | 欧美精品黄| 亚洲视频 欧美视频 | 日韩三 | 日韩视频福利 | 欧美一级黄色片免费观看 | 欧美视频在线看 |