📄 fiber-232-485-422.c.bak
字号:
////////////////////////////////////
// 产品名称:RS232-485-422/光纤
// ================
// 1、编程:黄华林
// 2、日期:2003-09-30
////////////////////////////////////
// 维护记录
// ==========
// 1、黄华林,2003-09-30完成程序编写,确定为V1.0;
//
#include <CPU_AT89C2051.H>
// 类型定义
#define BYTE char
#define UINT unsigned int
#define BOOL char
//////////////////////
// 硬件引脚功能定义 //
//////////////////////
sbit b485_232 = P1 ^ 6; // 硬件接口模式检测:0-RS232模式,1-RS485/422模式(方向:输入)
sbit b_RE485 = P1 ^ 7; // 全半双工检查,RS485收发控制:0-RS485接收使能(状态),1-RS485发送使能(状态)(方向:输入/出)
sbit bWdiClr = P3 ^ 0; // 看门狗清零(方向:输出)
sbit bRxdTTL = P3 ^ 2; // 接收电平
sbit bRunLed = P3 ^ 7; // 运行指示LED(方向:输出)
BYTE bHardMode; // 外部硬件接口模式
#define cnRS485_RecvMode 0x00 // 使RS485处于接收状态
#define cnRS485_SendMode 0xFF // 使RS485处于发送状态
#define cnFull232 0 // 半双工232
#define cnHalf485 1 // 半双工485
#define cnFull422 2 // 半双工422
//////////////
// 时钟计数 //
//////////////
UINT uiUs10Count; // 用于10us计时
UINT uiU10Sec250; // 用于250毫秒钟计时
bit b250MilSecPassed; // 已经过了250毫秒, LED-RUN
// 运行/调试状态指示LED:强制闪烁,使RUN状态LED闪烁周期小于1.5s
void vHitWdFlashRunLed()
{
bRunLed = ~bRunLed; // 为程序运行指示,低电平亮;
bWdiClr = ~bWdiClr; // 看门狗清零;
}
// 中断服务初始化
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 = 1; // 外部中断0允许
ET1 = 0; // 定时器1禁止中断
EX1 = 0; // 外部中断1禁止
PS = 0; // 串口中断优先级低
ES = 0; // 串口中断禁止
IT0 = 1; // 外部中断0外下降沿有效
IT1 = 1; // 外部中断1外下降沿有效
PX0 = 1; // 外部中断0优先级高
PX1 = 0; // 外部中断0优先级低
// =================================================
// 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.11824MHz / 12分频 = 计数频率为1.8432MHz,10个us的设置(115200bps)
// (2^8 - TL) / (1.8432 * 10^6) = 10 * 10^(-6) ==> TL ≈ 238
TH0 = TL0 = 238;
ET0 = 1; // 定时器0允许中断
TR0 = 1; // T0使能
EA = 1; // 中断允许总控制
}
// T0中断服务程序: 10us中断一次
void timer0() interrupt 1
{
uiUs10Count ++; // 用于10us计时
uiU10Sec250 ++; // 用于250毫秒钟计时
if (uiU10Sec250 >= 25000)
{
uiU10Sec250 = 0;
b250MilSecPassed = 1; // 已经过了250毫秒, LED-RUN
}
}
// 外部中断0服务程序
void extINT0() interrupt 0
{
if (bHardMode == cnHalf485) // 半双工485
{
if (b_RE485 == cnRS485_RecvMode) // 若RS485处于接收状态
{
b_RE485 = cnRS485_SendMode; // 使RS485处于发送状态
uiUs10Count = 0; // 重新计数
}
}
}
main()
{
long lCharDelay; // 1个字节的时间要求(按1B、8D、1P、1S计算)
// 一个字节的延时 = 11 * 1000000 / Baudrate
// Baudrate = 75 * (1 << ((P1 >> 2) & 0x0F))
// 1位时间结果 = 1000000 / (75 * (1 << ((P1 >> 2) & 0x0F))
//
lCharDelay = (P1 >> 2) & 0x0F; // P1.5432(实际波特率 = 2^P1.5432 * 75 bps,范围:75~2,457,600 bps),默认为9600、0111
lCharDelay = 1 << lCharDelay; // 计算 2^P1.5432
lCharDelay = 75 * lCharDelay; // 波特率 = 计算 2^P1.5432 * 75
lCharDelay = 1000000 / lCharDelay; // 1位时间 = 1000000 / 75 /(2^P1.5432)
lCharDelay = 11 * lCharDelay; // 11位时间
uiUs10Count = 0; // 用于10us计时
uiU10Sec250 = 0; // 用于250毫秒钟计时
b250MilSecPassed = 0; // 已经过了250毫秒, LED-RUN
bRunLed = 0; // 运行指示LED
bWdiClr = 0; // 看门狗清零
//////////////////////
// 硬件引脚功能定义 //
//////////////////////
b485_232 = 0xFF; // 硬件接口模式检测:0-RS232模式,1-RS485/422模式(方向:输入)
if (b485_232) // 1-RS485/422
{
b_RE485 = 0xFF; // 全半双工检查,RS485收发控制:0-RS485接收使能(状态),1-RS485发送使能(状态)(方向:输入/出)
if (b_RE485)
bHardMode = cnHalf485; // 半双工485
else
bHardMode = cnFull422; // 半双工422
b_RE485 = cnRS485_RecvMode; // 使RS485处于接收状态
}
else // 0-RS232
{
bHardMode = cnFull232; // 半双工232
b_RE485 = cnRS485_SendMode; // 使RS485处于发送状态
}
vInterruptInitialize(); // 中断初始化
do
{
if (b250MilSecPassed)
{
b250MilSecPassed = 0; // 已经过了250毫秒, LED-RUN
vHitWdFlashRunLed(); // 运行/调试状态指示LED:强制闪烁,使RUN状态LED闪烁周期小于1.5s
// 提高外部硬件接口的可靠性
switch(bHardMode)
{
case cnFull232: // 全双工232
b_RE485 = cnRS485_SendMode; // 使RS485处于发送状态
break;
case cnHalf485: // 半双工485
// nothing
break;
case cnFull422: // 全双工422
b_RE485 = cnRS485_RecvMode; // 使RS485处于接收状态
break;
}
}
if (bHardMode == cnHalf485) // 半双工485
if (b_RE485 == cnRS485_SendMode) // 若RS485处于发送状态
if (bRxdTTL) // 接收TTL处于“1”状态
if (uiUs10Count >= lCharDelay) // 已经达到1个字节的时间要求
b_RE485 = cnRS485_RecvMode; // 使RS485处于接收状态
} while(1);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -