📄 testcom.c
字号:
#include <CPU.H>
// 类型定义
#define BYTE unsigned char
#define UINT unsigned int
#define BOOL unsigned int
#define ULNG unsigned long
///////////////////
// 硬件引脚功能定义 //
///////////////////
sbit bCSX = P1^4; // p1.4(PLCC44-P6)为程序运行指示,低电平亮;
////////////
// 时钟计数 //
////////////
BYTE ucMsCount; // 用于1ms计时(受GPS脉冲控制)
UINT uiMsNow; // 当前毫秒数(受GPS脉冲控制)
bit b250MsPassed; // 已经过了250毫秒, LED-RUN
bit bOneSecPassed; // 已经过了1秒
BYTE ucSecCount; // 用于1s计时(受GPS脉冲控制)
bit bOneMinPassed; // 每分钟,重新初始化一次串口,以提高可靠性
// 中断服务初始化
void vInterruptInitialize()
{
// =====================================================
// IE:中断允许寄存器;复位后:IE = 0x00;1允许,0-禁止;
// =====================================================
// D7 D6 D5 D4 D3 D2 D1 D0
// -----------------------------------------------------
// EA ET2 ES ET1 EX1 ET0 EX0
// -----------------------------------------------------
// EX0,EX1:外部中断0、1的中断允许位;
// ET0,ET1:定时器/计数器0、1(T/C0,T/C1)溢出中断允许位;
// ES:串口中断允许位;
// ET2:定时器/计数器2(T/C2)溢出中断允许位;
// EA:CPU总的中断允许;
// -----------------------------------------------------
// =================================================
// IP:中断优先级寄存器;复位后:IP = 0x00;1→高,0→低;
// =================================================
// D7 D6 D5 D4 D3 D2 D1 D0
// -------------------------------------------------
// PT2 PS PT1 PX1 PT0 PX0
// -------------------------------------------------
// PX0,PX1:外部中断0、1中断优先级控制位;
// PT0,PT1:定时器/计数器0、1中断优先级控制位;
// PS:串口中断优先级控制位;
// PT2:定时器/计数器2(T/C2)中断优先级控制位;
// -------------------------------------------------
// ======================================================
// TCON:定时器/计数器控制寄存器;复位后:TCON = 0x00
// ======================================================
// D7 D6 D5 D4 D3 D2 D1 D0
// --------------------------------------------------------
// TF1 TR1 TF0 TR0 IE1 IT1 IE0 IT0
// --------------------------------------------------------
// TF1,TF0:定时器x溢出中断标志,当定时器x溢出时由内部硬件至置位,
// 当CPU转向中断服务程序时,由内部硬件清除;
// TR1,TR0:定时器运行控制位,由软件置位、清除来控制定时器开启、关闭;
// IE1,IE0:外部触发中断请求标志;
// IT1,IT0:外部中断触发方式,1-下降沿触发;0-低电平触发;
// --------------------------------------------------------
EA = 0; // 中断允许总控制
EX0 = 0; // 外部中断0允许
EX1 = 0; // 外部中断1允许
IT0 = 0; // 外部中断0外下降沿有效
IT1 = 0; // 外部中断1外下降沿有效
PS = 1; // 串口中断优先级高
ES = 1; // 串口中断使能
PX0 = 0; // 外部中断0优先级低
PX1 = 0; // 外部中断1优先级低
ET1 = 0; // 定时器1禁止中断
// =================================================
// TMOD: 定时器工作方式控制寄存器,复位后TMOD = 0x00
// =================================================
// D7 D6 D5 D4 D3 D2 D1 D0
// -------------------+---------------------------
// GATE C//T M1 M0 | GATE C//T M1 M0
// -------------------+---------------------------
// ------ 定时器1 -----+--- 定时器0 ---------------
// M1、M0:工作方式设置;
// 00-13位计数器;
// 01-16位计数器;
// 10-可自动再装入的8位计数器(从THx中自动装到TLx中);
// 11-把定时器分为两个8为的计数器或关闭定时器1;
// C//T:1-计数器功能,0-定时器功能;
// GATE:选通控制;1-同时/INTx为高电平且TRx为1时选通定时器x;
// 0-每当TRx为1时就选通定时器x;
// -----------------------------------------------------
// 定时器/计数器0初始化
TMOD = (TMOD & 0xF0) | 0x2; // T0工作于:10-可自动再装入的8位计数器(从THx中自动装到TLx中);
// 22.1184MHz / 12分频 = 计数频率为1.8432MHz,100个us的设置
// (2^8 - TL) / (1.8432 * 10^6) = 10^(-4) ==> TL ≈ 72
TH0 = TL0 = 72;
ET0 = 1; // 定时器0允许中断
TR0 = 1; // T0使能
EA = 1; // 中断允许总控制
}
// 串口初始化
#define cnBaudRate 19200 // 19200bps、8、N、1
#define cnFosc 22118400 // 当前晶振: 22.1184MHz
bit bComSendBufEmpty; // 串口的发送缓冲区空的标志: 用于启动TI
void vSerialInitialize()
{
// =====================================================================
// SCON:串口控制寄存器;复位后:SCON = 0x00;
// =====================================================================
// D7 D6 D5 D4 D3 D2 D1 D0
// ---------------------------------------------------------------------
// SM0 SM1 SM2 REN TB8 RB8 TI RI
// ---------------------------------------------------------------------
// SM1.SM0串口工作方式控制:
// 00-同步移位寄存器fosc/12;移位寄存器工作方式;
// 01-异步收发,由定时器控制;8位数据位的UART工作方式;
// 10-异步收发,fosc/32或fosc/64;9位数据位的UART工作方式;
// 11-异步收发,由定时器控制;9位数据位的UART工作方式;
// 波特率:
// 00-同步fosc/12;
// 01.03-异步,
// 1. 16位定时器1的溢出中断,2^SMOD * 定时器1的溢出率 / 32;例,要
// 取得110bps,定时器1的溢出率为32*110=3520,定时器1是加1定时器,
// 每12个振荡周期加1,因此当fosc=12MHz时,定时器每隔284us中断一次:
// fosc / (12 * 3520) = 12 * 10^6 / (12 * 2520) = 284us
// 考虑到溢出中断后CPU响应中断以及进行TH、TL的软件重装需要时间,
// 因此扣除8个us,则定时器1在装入后定时276us发生一次中断,可以计算
// 得到TH1=FEH、TL1=EBH。
// 常用波特率与其他参数的选取关系
// --------------------------------------------------------------
// 串口 波特率 fosc=6MHz fosc=12MHz fosc=11.0592Hz
// 工作方式 SMOD TMOD TH1 SMOD TMOD TH1 SMOD TMOD TH1
// --------------------------------------------------------------
// 方式0 1M x x x
// --------------------------------------------------------------
// 方式2 375k 1 x x
// 187.5k 1 x x 0 x x
// --------------------------------------------------------------
// 62.5k 1 20 FF
// 19.2k 1 20 FD
// 9.6k 0 20 FD
// 4.8k 1 20 F3 0 20 FA
// 方式1 2.4k 1 20 F3 0 20 F3 0 20 F4
// 或 1.2k 1 20 E6 0 20 E6 0 20 E8
// 方式3 600 1 20 CC 0 20 CC 0 20 D0
// 300 0 20 CC 0 20 98 0 20 A0
// 137.5 1 20 1D 0 20 1D 0 20 2E
// 110 0 20 72 0 10 FEEB 0 10 FEFF
// --------------------------------------------------------------
// 2. 自动重载方式的定时器2,TMOD=0010xxxx,则2^SMOD * fosc / (32 * 12 * (256 - TH1));
// 3. SMOD为PCON的最高位;
// 02-异步,fosc/32或fosc/64;
// SM2:多机通信控制为:1-收到第9位(RB8)为1,RI置1;0-接收到字符RI就置1;方式0时,SM2应为0;
// REN:串口接收允许位:1-允许;0-禁止;
// TB8:方式2和3时为发送的第9位数据,由软件置位或清零;可以作为奇偶校验位,或多机通信中表示地址或数据(1/0);
// RB8:方式2和3时为接收到的第9位数据,作为奇偶校验位,或多机通信的地址或数据(1/0);方式1时,为接收到的停止位;
// TI:发送中断标志:由硬件置位,必须由软件清零;
// RI:接收中断标志:由硬件置位,必须由软件清零;
// -----------------------------------------------------------------------------------
// 波特率设置技术:波特率随串口工作方式、晶振频率、电源控制PCON的SMOD等有关,另外与定时器T1设置也有关
// 1. 方式0: 波特率 = fosc / 12;
// 2. 方式2: 波特率 = fosc / 64 (SMOD=0)、fosc / 32 (SMOD=1);
// 3. 方式1和3:
// 波特率 = T1溢出率 / n,n = 32或64,
// T1溢出率 = 计数速率 / (256 - X)
// T1为工作于方式2,即自动重装载方式,X为TH1和TL1中装入的初始计数值;
// 计数速率:定时器1的计数速率与定时器的工作方式选择有关。当选择T1为定时工作方式时,
// 计数速率 = fosc / 12,
// 由此可得,
// 波特率 = (2 ^ SMOD) / 32 * fosc / 12 /(256 - X)
// = (2 ^ SMOD) * fosc / (32 * 12 * (256 - X))
//
// X = 256 - (2 ^ SMOD) * fosc / (32 * 12 * 波特率)
// = 256 - (2 ^ SMOD) * fosc / (384 * 波特率)
//
// 例如:
// 假定波特率要求为9600bps,系统晶振为fosc=11.0592MHz,当SMOD=1时,TH1和TL1的初值:
//
// 波特率 = 2 * 11.0592 * (10^6) / (32 * 12 * (256 - X)),
// X = 256 - 2 * 11059200 / (384 * 9600)) = 250 = FAH,
//
// THTL = FAH,波特率 = 9599.836bps,误差 = 0.00177%;
// -----------------------------------------------------------------------------------
// 数据位、奇偶校验位和停止位的不同:
// (1B、8D、0P、1S)1位起始位、8位数据位、0位奇偶位、1位停止位;或者,
// (1B、7D、1P、1S)1位起始位、7位数据位、1位奇偶位、1位停止位;或者,
// (1B、7D、0P、2S)1位起始位、7位数据位、0位奇偶位、2位停止位;或者,
// (1B、8D、1P、1S)1位起始位、8位数据位、1位奇偶位、1位停止位;或者,
// (1B、8D、0P、2S)1位起始位、8位数据位、0位奇偶位、2位停止位;
//
// PSW.0是每一指令周期累加器A的奇偶标志,由硬件置位或清零;A中1的个数为偶数,则PSW.0为0;为奇数,
// PSW.0为1。因此,可以利用累加器A来完成不同方式下的通信需求。
//
// 设置采用:
// (1B、8D、0P、1S)、(1B、7D、1P、1S)和(1B、7D、2S)采用:
// 01-异步收发,由定时器控制;8位数据位的UART工作方式;SM2=0:接收到字符RI就置1;
// (1B、8D、1P、1S)和(1B、8D、2S)采用:
// 11-异步收发,由定时器控制;9位数据位的UART工作方式;SM2=0:接收到字符RI就置1;
//
// 数据发送:
// (1B、8D、0P、1S)1位起始位、8位数据位、0位奇偶位、1位停止位;
// 。发送该字节
//
// (1B、7D、1P、1S)1位起始位、7位数据位、1位奇偶位、1位停止位;
// 。将发送的字节屏蔽bit7后送入A,可以得到奇偶值P;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -