⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 testcom.c

📁 Keil C 51单片机串口通信程序, 通过该程序可以了解和使用单片机串口通信
💻 C
📖 第 1 页 / 共 2 页
字号:
#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 + -