基于STC12C5A60S2系列1T 8051單片機實現一主單片機與一從單片機進行雙向串口通信功能
- STC12C5A60S2系列1T 8051單片機管腳圖
- STC12C5A60S2系列1T 8051單片機串口通信介紹
- STC12C5A60S2系列1T 8051單片機串口通信的結構
- 基于STC12C5A60S2系列1T 8051單片機串口通信的特殊功能寄存器列表
- 基于STC12C5A60S2系列1T 8051單片機串口通信用到的特殊功能寄存器
- STC12C5A60S2系列1T 8051單片機輔助寄存器AUXR
- STC12C5A60S2系列1T 8051單片機輔助寄存器AUXR1
- 串口1控制寄存器SCON
- 串口電源控制寄存器PCON
- 串口數據緩沖寄存器SBUF
- 串口輔助寄存器AUXR
- 串口中斷寄存器
- 基于STC12C5A60S2系列1T 8051單片機串口1通信工作模式
- 串口1通信模式0
- 串口1通信模式1
- 串口1通信模式2
- 串口1通信模式3
- 串口通信波特率設置
- 基于STC12C5A60S2系列1T 8051單片機實現一主單片機與一從單片機進行雙向串口通信功能介紹
- 串口通信簡單介紹
- 基于STC12C5A60S2系列1T 8051單片機實現一主單片機與一從單片機進行雙向串口通信功能電路連接及工作原理
- 電路連接
- 工作原理
- 基于STC12C5A60S2系列1T 8051單片機實現一主單片機與一從單片機進行雙向串口通信功能編程
- 主單片機程序
- 從單片機程序
- 基于STC12C5A60S2系列1T 8051單片機實現一主單片機與一從單片機進行雙向串口通信功能實現結果
STC12C5A60S2系列1T 8051單片機管腳圖
# STC12C5A60S2系列1T 8051單片機I/O口各種不同工作模式及配置
# STC12C5A60S2系列1T 8051單片機I/O口各種不同工作模式介紹
STC12C5A60S2系列1T 8051單片機串口通信介紹
STC12C5A60S2系列1T 8051單片機串口通信的結構
基于STC12C5A60S2系列1T 8051單片機串口通信的特殊功能寄存器列表
基于STC12C5A60S2系列1T 8051單片機串口通信用到的特殊功能寄存器
STC12C5A60S2系列1T 8051單片機輔助寄存器AUXR
作用:用來設置STC12C5A60S2系列1T 8051單片機串口通信類型、波特率
STC12C5A60S2系列1T 8051單片機輔助寄存器AUXR1
作用:用來設置STC12C5A60S2系列1T 8051單片機串口通信引腳切換
串口1控制寄存器SCON
作用:用來設置STC12C5A60S2系列1T 8051單片機串口通信以下功能
(1)、設置串口通信工作模式
(2)、設置串口方式2或方式3多機通信
(3)、設置串口通信允許接收
(4)、設置串口通信在方式2或方式3下發送第9位數據
(5)、設置串口通信通信在方式2或方式3下接收第9位數據
(6)、設置串口通信發送中斷請求
(7)、設置串口通信接收中斷請求
串口電源控制寄存器PCON
作用:用來設置STC12C5A60S2系列1T 8051單片機串口通信以下功能
(1)、設置串口通信波特率選擇
(2)、設置串口通信幀錯誤檢測有效控制
串口數據緩沖寄存器SBUF
作用:用來設置STC12C5A60S2系列1T 8051單片機串口通信發送或接收數據
串口輔助寄存器AUXR
作用:用來設置STC12C5A60S2系列1T 8051單片機串口通信類型、波特率
串口中斷寄存器
作用:用來設置STC12C5A60S2系列1T 8051單片機串口通信中斷允許、中斷優先級
基于STC12C5A60S2系列1T 8051單片機串口1通信工作模式
串口1通信模式0
串口1通信模式1
串口1通信模式2
串口1通信模式3
串口通信波特率設置
基于STC12C5A60S2系列1T 8051單片機實現一主單片機與一從單片機進行雙向串口通信功能介紹
串口通信簡單介紹
基于STC12C5A60S2系列1T 8051單片機實現一主單片機與一從單片機進行雙向串口通信功能電路連接及工作原理
電路連接
工作原理
主單片機先給從單片機發送數據 從單片機接收主單片機發送來的數據后 再把這個數據返回給主單片機發送數據
基于STC12C5A60S2系列1T 8051單片機實現一主單片機與一從單片機進行雙向串口通信功能編程
主單片機程序
main.c
#include <stc12c5a60s2.h>
#include "Uart.h"
#include "Timer0.h"
#include "Key.h"
//#include "Digitron.h"
#include "stdio.h"
#define uchar unsigned char//自定義無符號字符型為uchar
#define uint unsigned int//自定義無符號整數型為uint
sbit LED = P1^6;//聲明單片機P1.6端口為LED接口 void PortModeSet()//端口模式設置函數
{P0M1 = 0x00;P0M0 = 0x00;P1M1 = 0x00;P1M0 = 0x00;P2M1 = 0x00;P2M0 = 0x00;P3M1 = 0x00;P3M0 = 0x00;P4M1 = 0x00;P4M0 = 0x00;}void main()//主函數
{
// uchar Data0 = 88;//定義數據變量為88
// uint Data1 = 1250;//定義數據變量為1250
// uint Data2 = 12.5;//定義數據變量為12.5
// uint Data = 55;//定義數據變量為55
// uchar ShiWeiData = Data / 10 + '0';//定義十位數值變量 取Data = 55 把數字55的十位數字5分解出來 注意分解出來的5是'5'表示字符5不是數字5 把字符5寫入單片機數據緩存器 單片機數據緩存器會把字符5發送給串口調試助手軟件接收區 如果串口調試助手軟件接收區選十六進制數模式顯示 那么字符5以ASCII碼對應的十六進制數模式給顯示出0x35來 如果串口調試助手軟件接收區選文本模式顯示 那么字符5以文本模式給顯示出數字5來 為什么數據分解后+'0'? 因為單片機運算字符是字符對應的ASCII碼的二進制數值或十進制數值或十六進制數值 這里取單片機運算字符對應的ASCII碼十進制數值 如:字符'0'的ASCII碼的十進制數是48 字符'1'的ASCII碼的十進制數是49 字符'2'的ASCII碼的十進制數是50 .... 字符'9'的ASCII碼的十進制數是57 而編譯器對于'0'會自動視為是'0'ASCII碼的十進制數48 舉例:拿Data = 251來分解 則有:Data/100=2 Data/10%10=5 data%10=1 要把數據型251轉化成字符串為"251" 可拆開看成'2' '5' '1' 它們對應的ASCII碼十進制數分別為50 53 49 而Data/100=2+'0'=2+48=50 Data/10%10=5+'0'=5+48=53 data%10=1+'0'=1+48=49 算出50 53 49這三個十進制數分別對上字符'2' '5' '1'的ASCII碼十進制數為50 53 49 這就是為什么數據分解后+'0'的原因
// uchar GeWeiData = Data % 10 +'0';//定義個位數值變量 取Data = 55 把數字55的個位數字5分解出來 注意分解出來的5是'5'表示字符5不是數字5 把字符5寫入單片機數據緩存器 單片機數據緩存器會把字符5發送給串口調試助手軟件接收區 如果串口調試助手軟件接收區選十六進制數模式顯示 那么字符5以ASCII碼對應的十六進制數模式給顯示出0x35來 如果串口調試助手軟件接收區選文本模式顯示 那么字符5以文本模式給顯示出數字5來 為什么數據分解后+'0'? 解釋同上PortModeSet();//端口模式設置函數Uart1Init();//串行口1工作模式1的8位串行口波特率可變初始化函數 波特率為9600bps 晶振為12MHzTimer0Init();//定時器0的16位定時模式1用12分頻定時2ms初始化函數 晶振為12MHz
// DigitronBootDisplay();//數碼管開機顯示函數
// printf("Wait For Serial Communication Test Start....\r\n");//打印提示語句
// printf("Please Send a Frame Of Data....\r\n");//打印提示語句while(1)//主循環{ KeyScanResult();//按鍵掃描結果函數
// SendData('8');//注意'8'表示字符8不是數字8 把字符8寫入單片機數據緩存器 單片機數據緩存器會字符8發送給串口調試助手軟件接收區 如果串口調試助手軟件接收區選十六進制數模式顯示 那么字符8以ASCII碼對應的十六進制數模式給顯示出0x38來 如果串口調試助手軟件接收區選文本模式顯示 那么字符8以文本模式給顯示出數字8來
// SendData('\r');//回車 ASCII碼對應的十六進制數為0x0a
// SendData('\n');//換行 ASCII碼對應的十六進制數為0x0d
// SendString("Hello World!\r\n");//發送字符串函數
// printf("Hello World!\r\n");//打印字符串
// printf("Data0 = %bu\r\n",Data0);//打印無符號字符型數據
// printf("Data1 = %u\r\n",Data1);//打印無符號整數型數據
// printf("Data2 = %f\r\n",Data2);//打印單精度浮點型數據
// SendData('a');//把字符a寫入單片機數據緩存器 單片機數據緩存器會字符a發送給串口調試助手軟件接收區 如果串口調試助手軟件接收區選十六進制數模式顯示 那么字符a以ASCII碼對應的十六進制數模式給顯示出0x61來 如果串口調試助手軟件接收區選文本模式顯示 那么字符a以文本模式給顯示出字符a來
// SendData('1');//注意'1'表示字符1不是數字1 把字符1寫入單片機數據緩存器 單片機數據緩存器會字符1發送給串口調試助手軟件接收區 如果串口調試助手軟件接收區選十六進制數模式顯示 那么字符1以ASCII碼對應的十六進制數模式給顯示出0x31來 如果串口調試助手軟件接收區選文本模式顯示 那么字符1以文本模式給顯示出數字1來
// SendData(ShiWeiData);//發送數據Data的十位數
// SendData('\r');//換行
// SendData('\n');//回車
// SendData(GeWeiData);//發送數據Data的個位數if(ReceiveOverDataFlag == 1)//判斷接收完數據標志位變量是否置1 即主單片機串行口數據緩存器已經接收完從單片機發送來的數據{ReceiveOverDataFlag = 0;//接收完數據標志位變量清0LED = 0;//點亮LED燈KeyPressNumber = ReceiveData;//接收數據變量含有的數值賦給按鍵按下數值變量 即主單片機串行口數據緩存器接收從單片機發送來的數據賦給按鍵按下數值變量
// RS485DIR = 1;//啟動RS485發送數據控制
// ReceiveData = ReceiveData + 1;//接收數據變量累加
// SendData(ReceiveData);//單片機通過串行口通信把來自計算機串口調試助手軟件從發送區發送來的數據發回給計算機串口調試助手軟件接收區顯示出來
// RS485DIR = 0;//啟動RS485接收數據控制 準備下一次收發數據循環
// printf("\r\n");//打印換行回車
// printf("%bd\r\n",ReceiveData);//打印整數數據}}}
Uart.c
/*****關于8051系列單片機定時器溢出率、波特率和定時器初值(定時計數初值)之間計算的知識點*****/
/****
一、定時器溢出率計算公式
1、定時器溢出率:定時器每秒溢出的次數
2、定時器溢出率計算公式表定時方式 分頻方式 公式
方式1:16位定時器 12分頻(即12T 默認值) Ft=晶振頻率/12/(65536-定時器初值)
方式2:8位定時器 12分頻(即12T 默認值) Ft=晶振頻率/12/(256-定時器初值)
方式1:16位定時器 1分頻(即1T) Ft=晶振頻率/1/(65536-定時器初值)
方式2:8位定時器 1分頻(即1T) Ft=晶振頻率/1/(256-定時器初值)
二、波特率計算公式
1、波特率:每秒傳輸二進制位數的多少
2、波特率計算公式表定時方式 分頻方式 公式
方式1:16位定時器T1 12分頻(即12T 默認值) 波特率=晶振頻率/12/(65536-定時器初值)/4
方式2:8位定時器T1 12分頻(即12T 默認值) 波特率=晶振頻率/12/(256-定時器初值)*2^SMOD/32
方式1:16位定時器T2 12分頻(即12T 默認值) 波特率=晶振頻率/12/(65536-定時器初值)/4
方式1:16位定時器T1 1分頻(即1T) 波特率=晶振頻率/1/(65536-定時器初值)/4
方式2:8位定時器T1 1分頻(即1T) 波特率=晶振頻率/1/(256-定時器初值)*2^SMOD/32
方式1:16位定時器T2 1分頻(即1T) 波特率=晶振頻率/1/(65536-定時器初值)/4
三、根據波特率計算定時器初值(定時器定時計數)定時方式 分頻方式 公式
方式1:16位定時器T1 12分頻(即12T 默認值) 定時器初值(定時計數)=65536-晶振頻率/(48*波特率)
方式2:8位定時器T1 12分頻(即12T 默認值) 定時器初值(定時計數)=256-晶振頻率*2^SMOD/(384*波特率)
方式1:16位定時器T2 12分頻(即12T 默認值) 定時器初值(定時計數)=65536-晶振頻率/(48*波特率)
方式1:16位定時器T1 1分頻(即1T) 定時器初值(定時計數)=65536-晶振頻率/(4*波特率)
方式2:8位定時器T1 1分頻(即1T) 定時器初值(定時計數)=256-晶振頻率*2^SMOD/(32*波特率)
方式1:16位定時器T2 1分頻(即1T) 定時器初值(定時計數)=65536-晶振頻率/(4*波特率)
*****/
#include "Uart.h"
#include "stdio.h"
#define uchar unsigned char //定義無符號字符
#define uint unsigned int //定義無符號整形
bit ReceiveOverDataFlag = 0;//定義接收完數據標志位變量為0
uint ReceiveData = 0;//定義接收數據變量為0void Uart1Init()//串行口1工作模式1的8位串行口波特率可變初始化函數 波特率為9600bps 晶振為12MHz
{SCON = 0x50;//工作模式1的8位串行口波特率可變AUXR &= 0xBF;//定時器時鐘12T模式AUXR &= 0xFE;//串口1選擇定時器1為波特率發生器PCON &= 0x7f;//波特率不加倍TMOD &= 0x0f;//定時器/計數器工作模式清0TMOD |= 0x20;//設定定時器/計數器為定時器 工作模式為8位自動重裝定時器1模式2TH1 = 0xfd;//設定定時器1高八位初值TL1 = 0xfd;//設定定時器1低八位初值ET1 = 0;//禁止定時器1中斷ES = 1;//允許串行口1中斷EA = 1;//開總中斷TR1 = 1;//打開定時器1
// RS485DIR = 0;//啟動RS485接收數據控制}void MasterSendData(uint Data)//主單片機發送數據函數 即主單片機給從單片機發送數據
{SBUF = Data;//把數據變量Data含有數據寫入主單片機數據緩存器 主單片機數據緩存器會把數據變量Data含有數據發送給從單片機數據緩存器while(!TI)//當數據發送結束標志位變量TI為0 表示數據還沒發送完 若數據發送結束標志位變量TI為1 表示數據已發送完 從而觸發串口中斷 最后需在串口中斷程序中或者在其他程序中把數據發送結束標志位變量TI清0 才能進行下一次發送TI = 0<