大家好,我是遠方,這一章我們來學習下STC8G1K12的串口通信。
我們直接總結:
1.具有 2 個全雙工異步串行通信接口(串口 1、串口 2)。
2.串口 1 有 4 種工作方式,其中兩種方式的波特率是可變的,另兩種是固定的。串口 2 只有兩種工作方式,這兩種方式的波特率都是可變的。
3.可以通過功能管腳的切換功能切換到多組端口。
今天我們以串口1舉例,工作在模式1,用定時器2做波特率發生器。設置波特率為9600。然後在定製一個最簡單的協議通過串口控制LED。定時器的學習在上一講已經講過了,這一章就簡單帶過一下。
首先我們進行管腳的設置。
![宏晶科技 STC8G1K系列單片機教程「十」串口通信](http://p2.ttnews.xyz/loading.gif)
![宏晶科技 STC8G1K系列單片機教程「十」串口通信](http://p2.ttnews.xyz/loading.gif)
P_SW1中的S1_S[1:0]是串口 1 功能腳選擇位 ,我們最小系統的原理圖使用的是P3.0和P3.1口,這裡我們把這二位寫0即可。如果大家接的是其他端口,只需在這裡修改。
P_SW1 &= ~(1 << 6);P_SW1 &= ~(1 << 7); //串口 1 功能腳選擇位
SCON串口 1 控制寄存器 ,REN是串口接收控制位 ,0:禁止串口接收數據 1:允許串口接收數據 ,我們這裡寫1,允許接收,SM0寫0,SM1寫1,配置為模式1。
SCON = 0x50; //模式1 可變波特率8位數據方式
PCON電源管理寄存器 ,我們配置為波特率都不加倍 無幀錯檢測功能。
PCON &= 0x3F; //串口 1 的各個模式的波特率都不加倍 無幀錯檢測功能
AUXR輔助寄存器,我們選擇定時器 2作為波特率發射器 。
AUXR |= (1 << 0); //選擇定時器 2 作為波特率發射器
接下來是定時器2的相關配置。
跟定時器2相關的是 T2R T2_C/T T2x12 3位。
AUXR &= ~(1 << 4);//定時器 2 停止計數,配置完再打開。
AUXR &= ~(1 << 3);//清0則用作定時器
AUXR &= ~(1 << 2);//12T 模式,即 CPU 時鐘 12 分頻( FOSC/12)
T2L和T2H是定時器 2 計數寄存器,這裡的賦值關係到波特率的設置。我們依舊藉助於下載軟件中的工具波特率計算器。
通過計算得知,
T2L = 0xE8; //12T 模式 9600
T2H = 0xFF;
IP和IPH是優先級控制,我們這裡只有一箇中斷,就設置為最高級。
IP |= (1<<4);
IPH |= (1<<4);
最後面啟動定時器 2和使能串口1中斷
AUXR |= (1 << 4); //啟動定時器 2
ES = 1; //使能串口1中斷
串口1的相關配置已經講完了。開始寫代碼。我們先定個最簡單的協議,上位機發送0x55,LED亮,上位機發送0xAA,LED滅。然後下位機收到正確的命令後,作出相對應的響應。
全部工程代碼如下:
#include "STC8.H"
sbit LED = P1^1;
/*----------------------------
發送串口數據
----------------------------*/
void uart1_SendData(unsigned char dat)
{
SBUF = dat;
while (TI == 0);
TI = 0;
}
/*----------------------------
發送字符串
----------------------------*/
void uart1_SendDataFrame(unsigned char *pDat)
{
while ((*pDat) != '\\0')
{
uart1_SendData(*pDat++);
}
}
/*
上位機發送0x55,LED亮,上位機發送0xAA,LED滅。
然後下位機收到正確的命令後,作出相對應的相應。
*/
void UartIsr() interrupt 4
{
unsigned char data l_RevDat = 0;
if (RI)
{
RI = 0; //清除RI位
l_RevDat = SBUF;
if (0x55 == l_RevDat)
{
LED = 0;//LED亮
uart1_SendDataFrame("LED已點亮\\r\\n");
}
else if (0xAA == l_RevDat)
{
LED = 1;//LED滅
uart1_SendDataFrame("LED已熄滅\\r\\n");
}
else
{
uart1_SendDataFrame("指令錯誤\\r\\n");
}
}
}
void main(void)
{
//使用內部時鐘 燒錄軟件會幫我們配置好 如不懂 參考前面第3章系統設置學習。
// 燒錄軟件設置11.0592MHz為系統時鐘。以後我們的學習都是這個時鐘頻率。
P_SW2 |= (1<<7);
CKSEL = 0x00; //選擇內部 IRC ( 默認 )
P_SW2 &= ~(1<<7);
//配置端口 對於控制我們系統板的LED,配置準雙向口和推輓輸出都可以。
//只要是做為輸出,我建議全部設置為推輓輸出。
/*
PnM1.x PnM0.x Pn.x 口工作模式
0 0 準雙向口
0 1 推輓輸出
1 0 高阻輸入
1 1 開漏輸出
*/
P1M1 &= ~(1<<1); P1M0 |= (1<<1); //設置為推輓輸出
P_SW2 |= (1<<7);
P1PU = 0x00;//禁止P1端口內部的 3.7K 上拉電阻
P1NCS = 0xFF; //禁止P1端口的施密特觸發功能。
P_SW2 &= ~(1<<7);
/*串口1相關配置*/
P_SW1 &= ~(1 << 6);P_SW1 &= ~(1 << 7); //串口 1 功能腳選擇位
SCON = 0x50; //模式1 可變波特率8位數據方式
PCON &= 0x3F; //串口 1 的各個模式的波特率都不加倍 無幀錯檢測功能
AUXR |= (1 << 0); //選擇定時器 2 作為波特率發射器
AUXR &= ~(1 << 4);//定時器 2 停止計數,配置完再打開。
AUXR &= ~(1 << 3);//清0則用作定時器
AUXR &= ~(1 << 2);//12T 模式,即 CPU 時鐘 12 分頻( FOSC/12)
T2L = 0xE8; //12T 模式 9600
T2H = 0xFF;
IP |= (1<<4);//優先級控制
IPH |= (1<<4);
AUXR |= (1 << 4); //啟動定時器 2
ES = 1; //使能串口1中斷
EA = 1;//總中斷打開
LED = 1;//LED滅
while (1) ;
}
我們把程序編譯好,燒錄到板子裡面。連接好USB轉串口線,打開串口,波特率選擇9600。
發送0x55的指令,LED點亮,單片機返回“LED已點亮”
發送0xAA的指令,LED熄滅,單片機返回“LED已熄滅”
發送0xFE的指令,單片機返回“指令錯誤”
好了串口通訊這章就講到這裡。希望大家多多關注我的原創文章。謝謝。
閱讀更多 深漂遠方 的文章