導航:首頁 > 操作系統 > 51單片機單機串列通信程序

51單片機單機串列通信程序

發布時間:2022-05-29 23:27:05

❶ 兩個51單片機串口通信程序

串列發送程序 Tx.asm :
PCON, #00H ;; 波特率不倍增
SETB TR1 ;; 啟動定時器T1
MOV IE, #0 ;; 禁止任何中斷
CALL DLY125 ;; 延時125ms
;;--------------------------------------------
T_X: ;; 透傳發送字串

ACALL DSPLED ;; P2.0控制LED閃亮
MOV R3, #4 ;; 待發送字元個數
MOV DPTR, #TAB_TX ;; 數據表首址
TX_LP1: CLR A
MOVC A, @A+DPTR ;; A←數據表的1個字元
CLR TI ;; TI清零,允許發送
MOV SBUF,A ;; 發送1個字元
JNB TI, $ ;; 等待1個字元幀發送結束
DJNZ R3, TX_next
CALL DLY500 ;; 延時500ms
SJMP T_X ;; 重復發送
TX_next: ;; 發送另一字元
INC DPTR ;; 數據表指針移動
SJMP TX_LP1
;;--------------------------------------------
DSPLED: ;;開機或復位,P2.0控制LED閃亮6遍

MOV R2, #6 ;; 循環次數
LEDLP1: CLR P2.0 ;; LED亮
CALL DLY125 ;; 延時125ms
SETB P2.0 ;; LED滅
CALL DLY125
DJNZ R2,LEDLP1 ;; 循環
RET
;;----------------------------------------------
DLY125: ;; 延時125ms
DLY125A: MOV R5,#250
DLY125B: MOV R6,#250
DJNZ R6,$
DJNZ R5,DLY125B
RET
;; 250*250*2μs=125 000μs =125ms
;;----------------------------------------------
DLY500: ;; 延時500ms
MOV R7,#4
DLY500A: MOV R6,#250
DLY500B: MOV R5,#250
DJNZ R5,$
DJNZ R6,DLY500B
DJNZ R7,DLY500A
RET
;; 4*250*250*2μs=500 000μs =500ms
;;-------------------------------------------------

TAB_TX: DB 38H,30H,35H,31H, ...

;; 8 0 5 1 ...
;;----------------------------------------------
END

❷ 51單片機串口通信程序(需要判斷)

#include<reg51.h>
#define uchar unsigned char
uchar com1[]={0xef,0x01,0xff,0xff,0xff,0xff,0x01,0x00,0x03,0x01,0x00,0x05};
uchar red1[]={0xef,0x01,0xff,0xff,0xff,0xff,0x07,0x00,0x03,0x02,0x00,0x0c};
uchar red2[]={0xef,0x01,0xff,0xff,0xff,0xff,0x07,0x00,0x03,0x02,0x00,0x0a};
uchar red3[]={0xef,0x01,0xff,0xff,0xff,0xff,0x07,0x00,0x03,0x02,0x80,0x0a};
sbit p17=P1^7;
sbit p10=P1^0;
sbit p11=P1^1;
sbit p12=P1^2;
main()
{
uchar i,rdat[12];
TMOD=0x20;
TH1=0xfd;
TL1=0xfd;
TR1=1;
SCON=0x50;
while(1)
{
for(i=0;i<12;i++)
{
SBUF=com1[i];
while(!TI);
TI=0;
}
i=0;
while(i<12)
{
if(RI)
{
RI=0;
rdat[i]=SBUF;
i++;
}
}
for(i=0;i<12;i++)
{
if(rdat[i]!=red1[i])p17=1;
}
for(i=0;i<12;i++)
{
SBUF=com1[i];
while(!TI);
TI=0;
}
i=0;
while(i<12)
{
if(RI)
{
RI=0;
rdat[i]=SBUF;
i++;
}
for(i=0;i<12;i++)
{
if(rdat[i]!=red2[i])p10=1;
else if(rdat[i]!=red2[i])p11=1;
else p12=1;
}
}
}
}

❸ 51單片機串口通訊

51單片機串口通信
來源:維庫 作者:
關鍵字:51單片機 串口通信
這節我們主要講單片機上串口的工作原理和如何通過程序來對串口進行設置,以及根據所給出的實例實現與PC 機通信。
一、原理簡介
51 單片機內部有一個全雙工串列介面。什麼叫全雙工串口呢?一般來說,只能接受或只能發送的稱為單工串列;既可接收又可發送,但不能同時進行的稱為半雙工;能同時接收和發送的串列口稱為全雙工串列口。串列通信是指數據一位一位地按順序傳送的通信方式,其突出優點是只需一根傳輸線,可大大降低硬體成本,適合遠距離通信。其缺點是傳輸速度較低。
與之前一樣,首先我們來了解單片機串口相關的寄存器。
SBUF 寄存器:它是兩個在物理上獨立的接收、發送緩沖器,可同時發送、接收數據,可通過指令對SBUF 的讀寫來區別是對接收緩沖器的操作還是對發送緩沖器的操作。從而控制外部兩條獨立的收發信號線RXD(P3.0)、TXD(P3.1),同時發送、接收數據,實現全雙工。
串列口控制寄存器SCON(見表1) 。

表1 SCON寄存器
表中各位(從左至右為從高位到低位)含義如下。
SM0 和SM1 :串列口工作方式控制位,其定義如表2 所示。

表2 串列口工作方式控制位
其中,fOSC 為單片機的時鍾頻率;波特率指串列口每秒鍾發送(或接收)的位數。
SM2 :多機通信控制位。 該僅用於方式2 和方式3 的多機通信。其中發送機SM2 = 1(需要程序控制設置)。接收機的串列口工作於方式2 或3,SM2=1 時,只有當接收到第9 位數據(RB8)為1 時,才把接收到的前8 位數據送入SBUF,且置位RI 發出中斷申請引發串列接收中斷,否則會將接受到的數據放棄。當SM2=0 時,就不管第位數據是0 還是1,都將數據送入SBUF,並置位RI 發出中斷申請。工作於方式0 時,SM2 必須為0。
REN :串列接收允許位:REN =0 時,禁止接收;REN =1 時,允許接收。
TB8 :在方式2、3 中,TB8 是發送機要發送的第9 位數據。在多機通信中它代表傳輸的地址或數據,TB8=0 為數據,TB8=1 時為地址。
RB8 :在方式2、3 中,RB8 是接收機接收到的第9 位數據,該數據正好來自發送機的TB8,從而識別接收到的數據特徵。
TI :串列口發送中斷請求標志。當CPU 發送完一串列數據後,此時SBUF 寄存器為空,硬體使TI 置1,請求中斷。CPU 響應中斷後,由軟體對TI 清零。
RI :串列口接收中斷請求標志。當串列口接收完一幀串列數據時,此時SBUF 寄存器為滿,硬體使RI 置1,請求中斷。CPU 響應中斷後,用軟體對RI 清零。
電源控制寄存器PCON(見表3) 。

表3 PCON寄存器

表中各位(從左至右為從高位到低位)含義如下。
SMOD :波特率加倍位。SMOD=1,當串列口工作於方式1、2、3 時,波特率加倍。SMOD=0,波特率不變。
GF1、GF0 :通用標志位。
PD(PCON.1) :掉電方式位。當PD=1 時,進入掉電方式。
IDL(PCON.0) :待機方式位。當IDL=1 時,進入待機方式。
另外與串列口相關的寄存器有前面文章敘述的定時器相關寄存器和中斷寄存器。定時器寄存器用來設定波特率。中斷允許寄存器IE 中的ES 位也用來作為串列I/O 中斷允許位。當ES = 1,允許 串列I/O 中斷;當ES = 0,禁止串列I/O 中斷。中斷優先順序寄存器IP的PS 位則用作串列I/O 中斷優先順序控制位。當PS=1,設定為高優先順序;當PS =0,設定為低優先順序。
波特率計算:在了解了串列口相關的寄存器之後,我們可得出其通信波特率的一些結論:
① 方式0 和方式2 的波特率是固定的。
在方式0 中, 波特率為時鍾頻率的1/12, 即fOSC/12,固定不變。
在方式2 中,波特率取決於PCON 中的SMOD 值,即波特率為:

當SMOD=0 時,波特率為fosc/64 ;當SMOD=1 時,波特率為fosc/32。
② 方式1 和方式3 的波特率可變,由定時器1 的溢出率決定。

當定時器T1 用作波特率發生器時,通常選用定時初值自動重裝的工作方式2( 注意:不要把定時器的工作方式與串列口的工作方式搞混淆了)。其計數結構為8 位,假定計數初值為Count,單片機的機器周期為T,則定時時間為(256 ?Count)×T 。從而在1s內發生溢出的次數(即溢出率)可由公式(1)所示:

從而波特率的計算公式由公式(2)所示:

在實際應用時,通常是先確定波特率,後根據波特率求T1 定時初值,因此式(2)又可寫為:

51單片機串口通訊

二、電路詳解

下面就對圖1 所示電路進行詳細說明。
圖1 串列通信實驗電路圖
最小系統部分(時鍾電路、復位電路等)第一講已經講過,在此不再敘述。我們重點來了解下與計算機通信的RS-232 介面電路。可以看到,在電路圖中,有TXD 和RXD 兩個接收和發送指示狀態燈,此外用了一個叫MAX3232 的晶元,那它是用來實現什麼的呢?首先我們要知道計算機上的串口是具有RS-232 標準的串列介面,而RS-232 的標准中定義了其電氣特性:高電平「1」信號電壓的范圍為-15V~-3V,低電平「0」
信號電壓的范圍為+3V~+15V。可能有些讀者會問,它為什麼要以這樣的電氣特性呢?這是因為高低電平用相反的電壓表示,至少有6V 的壓差,非常好的提高了數據傳輸的可靠性。由於單片機的管腳電平為TTL,單片機與RS-232 標準的串列口進行通信時,首先要解決的便是電平轉換的問題。一般來說,可以選擇一些專業的集成電路晶元,如圖中的MAX3232。MAX3232 晶元內部集成了電壓倍增電路,單電源供電即可完成電平轉換,而且工作電壓寬,3V~5.5V 間均能正常工作。其典型應用如圖中所示,其外圍所接的電容對傳輸速率有影響,在試驗套件中採用的是0.1μF。
值得一提的是MAX3232 晶元擁有兩對電平轉換線路,圖中只用了一路,因此浪費了另一路,在一些場合可以將兩路並聯以獲得較強的驅動抗干擾能力。此外,我們有必要了解圖中與計算機相連的DB-9 型RS-232的引腳結構(見圖2)。

圖2 DB-9連接器介面圖
其各管腳定義如下(見表4)。

表4 DB-9型介面管腳定義
三、程序設計
本講設計實常式序如下:
#include "AT89X52.h" (1)
void Init_Com(void) ( 2)
{
TMOD = 0x20; ( 3)
PCON = 0x00; ( 4)
SCON = 0x50; ( 5)
TH1 = 0xE8; ( 6)
TL1 = 0xE8; ( 7)
TR1 = 1; ( 8)
}
void main(void) ( 9)
{
unsigned char dat; ( 10)
Init_Com(); ( 11)
while(1) ( 12)
程序詳細說明:
(1)頭文件包含。
(2)聲明串口初始化程序。
(3)設置定時器1 工作在模式2,自動裝載初值(詳見第二講)。
(4)SMOD 位清0,波特率不加倍。
(5)串列口工作在方式1,並允許接收。
(6)定時器1 高8 位賦初值。波特率為1200b/s(7)定時器1 低8 位賦初值。
(8)啟動定時器。
(9)主函數。
(10)定義一個字元型變數。
(11)初始化串口。
(12)死循環。
(13)如果接收到數據。
(14)將接收到的數據賦給之前定義的變數。
(15)將接收到的值輸出到P0 口。
(16)對接收標志位清0,准備再次接收。
(17)將接收到的數據又發送出去。
(18)查詢是否發送完畢。
(19)對發送標志位清0。
四、調試要點與實驗現象
接好硬體,通過冷啟動方式將程序所生成的。hex文件下載到單片機運行後,打開串口調試助手軟體,設置好波特率1200,復位單片機,然後在通過串口調試助手往單片機發送數據(見圖3),可以觀察到在接收窗口有發送的數據顯示,此外電路板上的串列通信指示燈也會閃爍,P0 口所接到LED 燈會閃爍所接收到的數據。

圖3 串口軟體調試界面
另外串口調試助手軟體使用時應注意的是,如果單片機開發板採用串口下載而且和串口調試助手是使用同一串口,則在打開串口軟體的同時不能給單片機下載程序,如需要下載,請首先點擊「關閉串口」,做發送實驗的時候,注意如果選中16 進制發送的就是數字或者字母的16 進制數值,比如發送「0」,實際接收的就應該是0x00,如果不選中,默認發送的是ASCII 碼值,此時發送「0」,實際接收的就應該是0x30,這點可以通過觀察板子P0 口上的對應的LED 指示出來。
五、總結
本講介紹了單片機串口通信的原理並給出了實例,通過該講,讀者可以了解和掌握51 單片機串口通信的原理與應用流程,利用串口通信,單片機可以與計算機相連,也可以單片機互聯或者多個單片機相互通信組網等,在實際的工程應用中非常廣泛。從學習的角度來說,熟練的利用串口將單片機系統中的相關信息顯示在計算機上可以很直觀方便的進行調試和開發。

❹ 高分求51單片機串口通信的程序

利用方式1實現單片機雙機通信,主頻為6M,波特率為2400bps,電路見圖5-10。當兩個單片機距離較近時,甲、乙兩機的發送端與接收端分別直接相聯,兩機共地。執行程序,甲機將亮燈信號發送給乙機,若通信正常,乙機接收到信號後點亮20個發光二極體。乙機採用查詢與中斷兩種工作方式。當然20個LED乙機可單獨控制,也可接受甲機的控制,並執行甲機指令,還需要進一步完善程序.
甲機發送程序:
org 0000h
sta: mov tmod,#20h ;設置波特率
mov tl1,#0FAh
mov th1,#0FAh
setb tr1
mov scon,#40h ;置工作方式1
clr ti
mov a,#00h
mov sbuf,a ;發送亮燈信號
wait: jbc ti,cont ;發送成功清標志
ajmp wait ;等待發送完畢
cont: sjmp sta ;重復發送
end

乙機查詢工作方式接收:

org 0000h
mov tmod,#20h ;設置通信波特率
mov tl1,#0FAh
mov th1,#0FAh
setb tr1
mov scon,#40h
clr ri
setb ren ;允許接收
wait: jbc ri,read ;接收成功清標志
ajmp wait ;接收未完等待
read: mov a ,sbuf
mov p1,a ;接收亮燈信號送P1口
sjmp $
end

乙機中斷工作方式接收
org 0000h
ajmp main
org 0023h
ajmp zd ;轉串口中斷程序
START: MOV TMOD,#20h
mov tl1,#0FAh
mov th1,#0FAh
setb tr1
mov scon,#50h
clr ri
mov ie,#90h ;開中斷

MAIN:sjmp $ 主程序
zd: clr ri ;清接收標志
;==============中斷程序還要再完善==============
mov a ,sbuf ;讀接收信號
mov p1,a
MOV R1,A ;將收到的信號送緩存
reti ;中斷返回
end

採用方式2 通信,數據幀格式是11位的,TB8為奇偶校驗位,接收過程要求判斷RB8,若出錯置F0標志為1,正確則置F0標志為0,然後返回。發送波特率375kbps,晶振為12MHz,所以SMOD=l。由於傳送數據的波特率與定時器無關,所以程序中無需對定時器編程.

send:
MOV SCON,#80H ;設置串列口為方式2
MOV PCON,#80H ;SMOD=l
MOV R0,#50H ;設數據塊指針
MOV R7,#20 ;設數據塊長度
STA: MOV A,@R0 ;取數據給A
MOV C,P
MOV TB8,C ;奇偶位P送給TB8,
MOV SBUF,A ;啟動發送
;====================================================
WAIT: JBC TI,CONT ;若發完一幀數據,清標志後發下一幀數據
AJMP WAIT ;未完等待
;=======================================================
CONT:INC R0 ;修改數據指針
DJNZ R7,STA ;循環發送至結束
RET
;========================================================
;乙機接收程序如下:
; 在進行雙機通信時,兩機應採用相同的工作方式和波特率。
;=============================================================
MOV SCON,#90H ;設置串列口為方式2,REN為1,允許接收
MOV PCON,#80H ;SMOD=1
MOV R0,#50H ;設置數據塊首址
MOV R7,#20 ;置數據塊長度
;=========================================================
WAIT:JBC RI,READ ;接收完一幀數據則RI清零並讀入數據
AJMP WAIT ;未完等待
;==========================================
READ:MOV A,SBUF ;讀入數據
JNB PSW.0,PZ ;收到數為偶數則轉
JNB RB8,ERR ;收到數為奇數,發端為偶數則通信出錯
SJMP RIGHT ;相符則正確
PZ:JB RB8,ERR ;收到數為偶數,發端為奇數則出錯
;========================================
RlGHT:MOV @R0,A ;通信正確,存放數據
INC R0 ;更改地址指針
DJNZ R7,WAIT ;數據塊接收完否,未完繼續
CLR PSW.5 ;通信正確,置F0為0
RET ;返回
ERROR:SETB PSW.5 ;通信出錯,置F0為l
RET ;返回

❺ 請問51單片機與51單片機之間的串口通信程序怎麼寫

1、查詢方式:
#include<reg51.h>
main()
{
unsigned char dat;
TMOD=0x20;
TH1=TL1=0xfd;
SCON=0x50;
TR1=1;
while(1)
{
if(RI)//接收
{
RI=0;
dat=SBUF;
}
SBUF=dat;//發送
while(!TI);
TI=0;
}
}
2、中斷方式:
#include<reg51.h>
unsigned char dat;
bit flag;
void uart_isr() interrupt 4
{
if(RI)//接收
{
RI=0;
dat=SBUF;
flag=1;
}
if(TI)TI=0;
}
main()
{
TMOD=0x20;
TH1=TL1=0xfd;
SCON=0x50;
TR1=1;
EA=1;
ES=1;
flag=0;
while(1)
{
if(flag)
{
SBUF=dat;
flag=0;
}
}
}

❻ 51單片機與PC串口通信程序,求指導 ! 具體要求如下:

功能如下:
1、程序燒進去,串口接收顯示一個菜單!《如圖》A、B、……分別代表一定的功能
例如:A項,代表修改ds1302的時間的數組
2、按照菜單的提示,如:發送A就進入了修改ds1302的時間函數,串口接收界面顯
示 A,像圖片那種,並顯示修改ds1302的操作方法,如從串口發送界面發送
0162115347就表示10年10月16日21時15分34秒星期7,
3、正如第二所說,馬上輸入1010162115347,就成功的修改了ds1302相關數據,
並返回change success!到串口界面!
4、設置一個功能就是返回主菜單界面。然後又可以就行第二、三步的操作!
5、通過串口,讀取單片機裡面相關的數據,如時鍾的數據
6、說明:可以不要ds1320相關的程序,可以用發光二極體亮來代表修改功能!

❼ 如何實現2個51單片機之間通過串口通信的源程序

匯編編寫的模擬串口通信程序

T2作為波特率控制
UART_RXD 是硬中斷0或1口,如果能進入中斷,說明該線有一個起始位產生,進入中斷後調
用下面的接收程序。退出硬中斷之前還需要將硬中斷標志重新復位。
UART_TXD是任何其它IO即可。

UART_SEND:
PUSH IE
PUSH DPH
PUSH DPL
PUSH PSW
PUSH 00H
PUSH ACC
CLR EA
SETB UART_TXD ;START BIT

MOV R0,A
CLR TR2 ;TR2置1,計數器2啟動,時間計數啟動。
MOV A,RCAP2L;計數器2重新裝載值
MOV TL2,A ;置計數器2初值 ;T2需要重新裝載
MOV A,DPH
MOV A,RCAP2H
MOV TH2,A
MOV A,R0

SETB TR2 ;TR2置1,計數器
JNB TF2,$
CLR TF2
JNB TF2,$
CLR TF2

CLR UART_TXD ;START BIT
JNB TF2,$
CLR TF2
JNB TF2,$
CLR TF2

MOV R0,#08H
UART_SEND_LOOP:
RRC A
MOV UART_TXD,C ;8 BIT
JNB TF2,$
CLR TF2
JNB TF2,$
CLR TF2
DJNZ R0,UART_SEND_LOOP

SETB UART_TXD ;END BIT
JNB TF2,$
CLR TF2
JNB TF2,$
CLR TF2

POP ACC
POP 00H
POP PSW
POP DPL
POP DPH
POP IE
RET

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
UART_REC:
PUSH IE
PUSH DPH
PUSH DPL
CLR EA

CLR TR2 ;TR2置1,計數器2啟動,時間計數啟動。
MOV A,RCAP2L;計數器2重新裝載值
MOV TL2,A ;置計數器2初值 ;T2需要重新裝載
MOV A,DPH
MOV A,RCAP2H
MOV TH2,A

JB UART_RXD,$ ;REC
SETB TR2 ;TR2置1,計數器2啟動,時間計數啟動。
JNB TF2,$
CLR TF2 ;0.5 BIT

JNB TF2,$
CLR TF2 ;1 BIT

JNB TF2,$
CLR TF2 ;1.5 BIT
MOV C,UART_RXD
MOV ACC.0,C

JNB TF2,$
CLR TF2

JNB TF2,$
CLR TF2 ;2.5
MOV C,UART_RXD
MOV ACC.1,C

JNB TF2,$
CLR TF2

JNB TF2,$
CLR TF2 ;3.5
MOV C,UART_RXD
MOV ACC.2,C

JNB TF2,$
CLR TF2

JNB TF2,$
CLR TF2 ;4.5
MOV C,UART_RXD
MOV ACC.3,C

JNB TF2,$
CLR TF2

JNB TF2,$
CLR TF2 ;5.5
MOV C,UART_RXD
MOV ACC.4,C

JNB TF2,$
CLR TF2

JNB TF2,$
CLR TF2 ;6.5
MOV C,UART_RXD
MOV ACC.5,C

JNB TF2,$
CLR TF2

JNB TF2,$
CLR TF2 ;7.5
MOV C,UART_RXD
MOV ACC.6,C

JNB TF2,$
CLR TF2

JNB TF2,$
CLR TF2 ;8.5
MOV C,UART_RXD
MOV ACC.7,C

JNB TF2,$
CLR TF2 ;9.5
JNB UART_RXD,$ ;等待停止位,並重新復位計數器
SETB UART_RXD

POP DPL
POP DPH
POP IE
RET
補充回答:
串口調試

1. 發送:向匯流排上發命令
2. 接收:從匯流排接收命令,並分析是地址還是數據。
3. 定時發送:從內存中取數並向主機發送.

經過調試,以上功能基本實現,可以通過上位機對單片機進行實時控制。

程序如下:

//這是一個單片機C51串口接收(中斷)和發送常式,可以用來測試51單片機的中斷接收
//和查詢發送,發送沒有必要用中斷,因為程序的開銷是一樣的

#include <reg51.h>
#include<stdio.h>
#include <string.h>

#define INBUF_LEN 4 //數據長度
unsigned char inbuf1[INBUF_LEN];

unsigned char checksum,count3 , flag,temp,ch;

bit read_flag=0;
sbit cp=P1^1;
sbit DIR=P1^2;

int i;

unsigned int xdata *RAMDATA; /*定義RAM地址指針*/
unsigned char a[6] ={0x11,0x22,0x33,0x44,0x55,0x66} ;

void init_serialcomm(void)
{
SCON=0x50; //在11.0592MHz下,設置串列口波特率為9600,方式1,並允許接收
PCON=0x00;
ES=1;
TMOD=0x21; //定時器工作於方式2,自動裝載方式
TH0=(65536-1000)%256;
TL0=(65536-1000)/256;
TL1=0xfd;
TH1=0xfd;
ET0=1;
TR0=1;
TR1=1;
// TI=0;
EA=1;
// TI=1;
RAMDATA=0x1F45;
}

void serial () interrupt 4 using 3
{
if(RI)
{ RI=0;
ch=SBUF;
TI=1; //置SBUF空
switch(ch)
{
case 0x01 :printf("A"); TI=0;break;
case 0x02 :printf("B"); TI=0;break;
case 0x03 :printf("C"); TI=0;break;
case 0x04 :printf("D"); TI=0;break;
default :printf("fg"); TI=0;break;
}
}
}

//向串口發送一個字元
void timer0() interrupt 1 using 3{
// char i;
flag++;
TH0=0x00;
TL0=0x00;
if(flag==10)
{// cp=!cp;
// for(i=0;i<6;i++)
P2=0x25;
TI=1;
temp=*RAMDATA;
printf("%c",temp);
TI=0;
// RAMDATA--;
flag=0;
}
}

//主程序
main()
{
init_serialcomm(); //初始化串口
//向6264中送數據
{
*RAMDATA=0x33;
}
while(1)

{
*RAMDATA=0x33;;
}
}

調試需要注意的問題:

1. 發送過程:在發送時必須保證TI=1:即發送緩沖器為空,否則將導致數據發不出去,如果想強制發送可以用:TI=1.具體發送數據:利用printf(「abcd」);函數直接發送即可。
2. 接收過程:在接收時多選用中斷方式,這樣可以節約CPU的時間,提高效率,

❽ 51單片機的串列口按工作方式1進行串列數據通信,假定波特率為2400b/s編寫程序

ORG 0000H
AJMP MAIN ;上電,轉向主程序
ORG 0023H ;串列口的中斷入口地址
AJMP SERVE ;轉向中斷服務程序
ORG 0040H ;主程序
MAIN: MOV SP,#60H ;設置堆棧指針
MOV SCON ,#50H
MOV PCON ,#00H
MOV TMOD,#20H
MOV TH1,#0F3H
MOV TL1,#0F3H
SETB TR1
MOV R0 ,#20H ;置發送數據區首地址
MOV R1 ,#40H ;置接收數據區首地址
MOV R7 ,#10H ;置發送位元組長度
MOV R6 ,#10H ;置接收位元組長度
SETB ES ;允許串列口中斷
SETB EA ;CPU允許中斷
MOV A ,@R0 ;取第一個數據發送
MOV SBUF ,A ;發送第一個數據
SJMP $ ;等待中斷
SERVE: JNB RI ,SEND ;TI=1,為發送中斷
CLR RI
MOV A ,SBUF ;讀出接收緩沖區內容
MOV @R1 ,A ;讀入接收緩沖區
DJNZ R6 ,L1 ;判斷數據塊發送完否
SJMP L2 ;數據塊接收完,轉L2
L1:INC R1 ;修改數據區指針
L2:RETI ;中斷返回
SEND:
CLR TI ;清除發送中斷標志
DJNZ R7 ,L3 ;判斷數據塊發送完否
SJMP L4 ;數據塊接收完,轉L4
L3: MOV A ,@R0 ;取數據發送
MOV SBUF ,A ;發送數據
INC R0 ;修改數據地址
L4:
RETI ;中斷返回
END

❾ 51單片機的串列通信

這個是單片機用18b20採集溫度,傳給電腦的程序;電腦那端用VB里的串口控制項就能捕獲了,你可以吧裡面發送出去的數據換成你採集的 你想加我的qq也行
-----------------------------------------
#include <AT89X51.H>
#include <intrins.h>
#define Key_UP P1_0
#define Key_DOWN P1_1
#define Key_SET P1_2
#define RelayOutPort P2_0
#define LEDPort P0
#define DELPort P2_1
#define LEDTwoC P3_6
#define LEDThreeC P3_7
#define TMPort P2_7
#define INBUF_LEN 5 //數據長度
unsigned char inbuf1[INBUF_LEN]={'0','0','0','0','0'};//發送緩沖區
unsigned char inbuf2[50];//接收緩沖區
unsigned char count3;
void init_serialcomm( void )
{
SCON = 0x50 ; //SCON: serail mode 1, 8-bit UART, enable ucvr
TMOD |= 0x20 ; //TMOD: timer 1, mode 2, 8-bit reload
PCON |= 0x80 ; //SMOD=1;
TH1 = 0xFA ; //Baud:4800 fosc=11.0592MHz
IE |= 0x90 ; //Enable Serial Interrupt
TR1 = 1 ; // timer 1 run
}
//向串口發送一個字元
void send_char_com( unsigned char ch)
{
SBUF=ch;
while (TI== 0 );
TI= 0 ;
}
//向串口發送一個字元串,strlen 為該字元串長度
void send_string_com( unsigned char *str, unsigned int strlen)
{
unsigned int k= 0 ;
do
{
send_char_com(*(str + k));
k++;
} while (k < strlen);
}
//串口接收中斷函數
void serial () interrupt 4 using 3
{
if (RI) //RI==開始接收
{
unsigned char ch;
RI = 0 ; //軟體RI=0
ch=SBUF;
if (ch> 1 )
{
count3= 0 ;
inbuf2[count3]=ch;
}
else
{
count3++;
inbuf2[count3]=ch;
}
}
} unsigned char code LEDDis[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0xFF,0xBF}; //0-9的LED筆劃,0xFF為空,0xF7為負號
unsigned char dis_8[12]={'0','1','2','3','4','5','6','7','8','9',' ','-'};
static unsigned char bdata StateREG; //可位定址的狀態寄存器
sbit DS1820ON = StateREG^0; //DS1820是否存在
sbit SetTF = StateREG^1; //是否是在溫度設置狀態
sbit KeySETDown = StateREG^2; //是否已按過SET鍵標識
sbit PowTF = StateREG^3; //電源電源標識
sbit KeyTF = StateREG^4; //鍵盤是否允許//sbit KeySETDowning = StateREG^5; //SET是否正在按下
static unsigned char bdata TLV _at_ 0x0029; //溫度變數高低位
static unsigned char bdata THV _at_ 0x0028;
static signed char TMV; //轉換後的溫度值
static unsigned char KeyV,TempKeyV; //鍵值
static unsigned char Second;
static unsigned char flag;
static signed char TMRomV _at_ 0x0027; //高溫限制
static signed char TMSetV _at_ 0x0026; //溫度設定值
static unsigned char KSDNum; //SET鍵連按時的採集次數
static unsigned char IntNum,IntNum2,IntNum3; //中斷發生次數,IntNum用於SET長按檢測,IntNum2用於設定狀態時LED閃爍
static signed char LED_One,LED_Two,LED_Three; //LED的顯示位 LED_One為十位,LED_Two為個位
static unsigned char Sign; //負號標識void main(void)
{ void InitDS1820(void); //定義函數
void ROMDS1820(void);
void TMVDS1820(void);
void TMRDS1820(void);
void TMWDS1820(void);
void TMREDS1820(void);
void TMERDS1820(void);
void ReadDS1820(void);
void WriteDS1820(void);
void Delay_510(void);
void Delay_110(void);
void Delay_10ms(void);
void Delay_4s(void);
void V2ToV(void);

DELPort=1;
StateREG = 0; //初始化變數
SetTF = 0;
PowTF = 0; //關電源
THV = 0;
TLV = 0;
TMV = 0;
KeyV = 0;
TempKeyV = 0;
KSDNum = 0;
IntNum = 0;
IntNum2 = 0;
IntNum3 = 0;
LED_One = 0;
LED_Two = 0; InitDS1820(); //初始化
ROMDS1820(); //跳過ROM
TMERDS1820(); //E2PRAM中溫度上限值調入RAM
InitDS1820(); //初始化
ROMDS1820(); //跳過ROM
TMRDS1820(); //讀出溫度指令
ReadDS1820(); //讀出溫度值和上限值
TMSetV = TMRomV; //拷貝保存在DS18B20ROM里的上限值到TMSetV EA = 1; //允許CPU中斷
ET0 = 1; //定時器0中斷打開
TMOD = 0x1; //設定時器0為模式1,16位模式
TH0=0xB1;
TL0=0xDF; //設定時值為20000us(20ms)
TR0 = 1;

while(1){ //開始定時
if (flag==0){
if (Second==1){
Delay_4s();
Delay_4s();
Delay_4s();
Delay_4s();
Delay_4s();
Delay_4s();

DELPort=0;
Second=0;
}
}
}

}//定時器0中斷外理中鍵掃描和顯示
void KeyAndDis_Time0(void) interrupt 1 using 2
{
TH0=0xB1;
TL0=0xDF; //設定時值為20000us(20ms) LEDPort = 0xFF;

if (inbuf2[0]==0x33){
send_char_com('O');
send_char_com('O');
send_char_com('O');
SetTF = 1;
//send_string_com(inbuf2,1);
//BEEP=0;
//RELAY=0;
send_char_com('O');
//inbuf2[0]=0x00;
inbuf2[0]=0x00;
} if (inbuf2[0]==0x36){//send_string_com(inbuf2,1);
//BEEP=1;
send_char_com('N');
send_char_com('N');
send_char_com('N');
SetTF = 0;inbuf2[0]=0x00;} if (inbuf2[0]==0x34){
KeyV=2;
//send_string_com(inbuf2,1);
//BEEP=0;
//RELAY=0;
TMSetV = TMSetV - 1;
inbuf2[0]=0x00;
} if (inbuf2[0]==0x35){//send_string_com(inbuf2,1);
//BEEP=1;
//RELAY=1;
TMSetV = TMSetV + 1; //上調溫度
inbuf2[0]=0x00;
} if (inbuf2[0]==0x74){
KeyV=2;
//send_string_com(inbuf2,1);
//BEEP=1;
//RELAY=1;
} if (inbuf2[0]==0x90){
KeyV=1;
//send_string_com(inbuf2,1);
//BEEP=1;
//RELAY=1;
}
if (!Key_UP)
KeyV = 1;
if (!Key_DOWN)
KeyV = 2;
if (!Key_SET)
KeyV = 3;
//KeySETDowning = 0; //清除
if (KeyV != 0) //有鍵按下
{
Delay_10ms(); //延時防抖 按下10ms再測
if (!Key_UP)
TempKeyV = 1;
if (!Key_DOWN)
TempKeyV = 2;
if (!Key_SET)
TempKeyV = 3;
if (KeyV == TempKeyV) //兩次值相等為確定接下了鍵
{
if (KeyV == 3) //按下SET鍵,如在SET狀態就退出,否則進入
{
//KeySETDowning = 1; //表明SET正在按下

PowTF = 0; //電源標識開
if (!KeyTF)
if (SetTF){
send_char_com('N');
send_char_com('N');
send_char_com('N');
SetTF = 0; //標識位標識退出設定

InitDS1820(); //初始化
ROMDS1820(); //跳過ROM
TMWDS1820(); //寫溫度上限指令
WriteDS1820(); //寫溫度上限到DS18B20ROM
WriteDS1820(); //寫溫度上限到DS18B20ROM
WriteDS1820(); //寫溫度上限到DS18B20ROM
InitDS1820(); //初始化
ROMDS1820(); //跳過ROM
TMREDS1820(); //溫度上限值COPY回E2PRAM
}
else {
send_char_com('O');
send_char_com('O');
send_char_com('O');
SetTF = 1;}

if (!KeySETDown) //沒有第一次按下SET時,KeySETDown標識置1
KeySETDown = 1;
else
KSDNum = KSDNum + 1; //前一秒內有按過SET則開始計數
}
if (SetTF) //在SET狀態下
{

if ((KeyV == 1) && (!KeyTF))
TMSetV = TMSetV + 1; //上調溫度
if ((KeyV == 2) && (!KeyTF))
TMSetV = TMSetV - 1; //下調溫度
if (TMSetV <= 20) //限制溫度上下限
TMSetV = 20;
if (TMSetV >= 75)
TMSetV = 75;
}
if ((!KeyTF) && (IntNum3 == 0)) KeyTF = 1; //當鍵盤處於可用時,鎖定
}
}
KeyV = 0;
TempKeyV = 0; //清空變數准備下次鍵掃描 if (!PowTF)
{
InitDS1820(); //初始化
ROMDS1820(); //跳過ROM
TMVDS1820(); //溫度轉換指令 Delay_510();
Delay_510(); //延時等待轉換完成 InitDS1820(); //初始化
ROMDS1820(); //跳過ROM
TMRDS1820(); //讀出溫度指令
ReadDS1820(); //讀出溫度值 V2ToV(); //轉換顯示值
if (TMV > TMSetV) //根據採集到的溫度值控制繼電器
{
RelayOutPort = 0;
flag=0;
}
else
{
RelayOutPort = 1;
DELPort=1;
Second=1;
flag=1;
} if (SetTF) IntNum2 = IntNum2 + 1; //用於閃爍計數
if (IntNum2 > 50 ) IntNum2 = 0;
if (KeyTF) IntNum3 = IntNum3 + 1; //用於防止按鍵連按
if (IntNum3 > 25)
{
IntNum3 = 0;
KeyTF = 0;
} if ((SetTF) && (IntNum2 < 25)) goto InitEnd; //計數在後半段時顯示

LEDPort = LED_Two;
LEDTwoC = 0;
Delay_510();
LEDTwoC = 1; //顯示十位數
LEDPort = LED_Three;
LEDThreeC = 0;
Delay_510();
LEDThreeC = 1; //顯示個位數
}
InitEnd:;
}void V2ToV(void) //數值轉換
{
TLV = TLV >> 4;
THV = THV << 4; //讀出的高低位數值移位
TMV = TLV | THV; //合並高低位放入TM為實際溫度值
Sign = 0;
if (SetTF || !Key_SET)
Sign = TMSetV >> 7; //取符號
else
Sign = TMV >> 7; if (Sign)
{
if (SetTF || !Key_SET)
{
LED_One = (~(TMSetV-1)) / 100; //SET狀態下顯示設定值
LED_Two = ((~(TMSetV-1)) - LED_One * 100)/10;
LED_Three = (~(TMSetV-1)) - LED_One * 100 - LED_Two * 10;
inbuf1[0]=dis_8[LED_Two];
inbuf1[1]=dis_8[LED_Three];
//inbuf1[2]=dis_8[ LED_Three];
inbuf1[2]=0x0d;
inbuf1[3]=0x0a;
}
else
{
LED_One = (~(TMV-1)) / 100; //轉換百位值
LED_Two = ((~(TMV-1)) - LED_One * 100)/10;
LED_Three = (~(TMV-1)) - LED_One * 100 - LED_Two * 10;
inbuf1[0]=dis_8[LED_Two];
inbuf1[1]=dis_8[LED_Three];
inbuf1[2]=dis_8[0];
inbuf1[3]=0x0d;
inbuf1[4]=0x0a;
}
}
else
{
if (SetTF || !Key_SET)
{
LED_One = (TMSetV) / 100; //SET狀態下顯示設定值
LED_Two = (TMSetV - LED_One * 100)/10;
LED_Three = TMSetV - LED_One * 100 - LED_Two * 10;
inbuf1[0]=dis_8[LED_Two];
inbuf1[1]=dis_8[LED_Three];
inbuf1[2]=dis_8[0];
inbuf1[3]=0x0d;
inbuf1[4]=0x0a;
}
else
{
LED_One = (TMV) / 100; //轉換百位值
LED_Two = (TMV - LED_One * 100)/10;
LED_Three = TMV - LED_One * 100 - LED_Two * 10;
inbuf1[0]=dis_8[LED_Two];
inbuf1[1]=dis_8[LED_Three];
inbuf1[2]=dis_8[0];
inbuf1[3]=0x0d;
inbuf1[4]=0x0a;
}
} init_serialcomm(); //初始化串口//while ( 1 )
//{
send_string_com(inbuf1,INBUF_LEN); //轉LED欄位
if (LED_One) //超過百時十位的處理
LED_Two = LEDDis[LED_Two];
else
{
if (LED_Two == 0)
LED_Two = LEDDis[10];
else
LED_Two = LEDDis[LED_Two];
}
if (Sign)
LED_One = LEDDis[11];
else
{
if (LED_One == 0)
LED_One = LEDDis[10];
else
LED_One = LEDDis[LED_One];
}
LED_Three = LEDDis[LED_Three];
}void InitDS1820(void) //初始化DS1820
{

}void ROMDS1820(void) //跳過ROM匹配
{}void TMVDS1820(void) //溫度轉換指令
{}void TMRDS1820(void) //讀出溫度指令
{}void TMWDS1820(void) //寫入溫度限制指令
{}void TMREDS1820(void) //COPY RAM to E2PRAM
{}void WriteDS1820(void) //寫入溫度限制值
{
}void ReadDS1820(void) //讀出溫度值
{}void Delay_510(void) //延時510微秒
{
}void Delay_10ms(void) //延時10ms
{
}void Delay_4s(void) //延時4s
{}

❿ C51單片機:設計一個串列通信程序,波特率為1200b/s,發送數據I Love U Forever

#include <reg51.h>
//晶振=12M
void InitUART(void)
{
TMOD = 0x20;
SCON = 0x40;
TH1 = 0xE6;
TL1 = TH1;
PCON = 0x00;
TR1 = 1;
}

void SendString(unsigned char *c)
{
while(*c)
{
SBUF = *c++;
while(!TI);
TI = 0;
}
}

void main(void)
{
InitUART();
SendString("I Love U Forever");
while(1);
}

閱讀全文

與51單片機單機串列通信程序相關的資料

熱點內容
自己購買雲主伺服器推薦 瀏覽:419
個人所得稅java 瀏覽:761
多餘的伺服器滑道還有什麼用 瀏覽:189
pdf劈開合並 瀏覽:27
不能修改的pdf 瀏覽:751
同城公眾源碼 瀏覽:488
一個伺服器2個埠怎麼映射 瀏覽:297
java字元串ascii碼 瀏覽:78
台灣雲伺服器怎麼租伺服器 瀏覽:475
旅遊手機網站源碼 瀏覽:332
android關聯表 瀏覽:945
安卓導航無聲音怎麼維修 瀏覽:332
app怎麼裝視頻 瀏覽:430
安卓系統下的軟體怎麼移到桌面 瀏覽:96
windows拷貝到linux 瀏覽:772
mdr軟體解壓和別人不一樣 瀏覽:904
單片機串列通信有什麼好處 瀏覽:340
游戲開發程序員書籍 瀏覽:860
pdf中圖片修改 瀏覽:288
匯編編譯後 瀏覽:491