单片机io程序C语言,52,IO 精心奉献:52单片机实用的IO模拟串行口C语言源程序

院士

2006-12-22 22:43:00    评分

2楼

/*

52单片机实用的IO模拟串行口C语言源程序

作者:21IC suda

用途:短距离、波特率要求不高、环境干扰不大的场合

特点:

程序简练、实用、移植方便

占用定时器T2

只消耗约600字节的ROM

有详细的注释

参数:

晶振:22.1184MHz

波特率:1200

起始位:1

数据位:8

校验位:无

停止位:1

*/

#include

//将T2定时器的自动重装寄存器定义成16位SFR,以方便访问

sfr16 RCAP2 = 0xCA;

//修改如下定义将方便程序移植

sbit RXD_pin = P3^0;  //定义接收引脚

sbit TXD_pin = P3^1;  //定义发送引脚

#define MAIN_CLK    22118400L    //定义主频

#define BAUD_RATE    1200L        //定义波特率(数值不能太高,因为要给T2中断服务程序留足执行时间)

#define HITS        8            //定义采样率(应当是偶数;减少采样率能提高波特率,但为保证可靠工作,最小不能少于6次)

#define RXD_BUF_LEN  32  //定义接收缓冲区大小

volatile unsigned char RXD_buf[RXD_BUF_LEN];  //定义接收缓冲区(循环队列)

volatile unsigned char RXD_p1;  //指向缓冲区,由中断程序自动修改

volatile unsigned char RXD_p2;  //指向缓冲区,由主程序修改

#define TXD_BUF_LEN  32  //定义发送缓冲区大小

volatile unsigned char TXD_buf[TXD_BUF_LEN];  //定义发送缓冲区(循环队列)

volatile unsigned char TXD_p1;  //指向TXD_buf,由主程序修改

volatile unsigned char TXD_p2;  //指向TXD_buf,由中断程序修改

//定时器T2初始化

extern void T2_init()

{

EA = 0;

T2CON = 0x00;

PT2 = 1;  //将T2中断设置成高级优先级

RCAP2 = 65536L - ( MAIN_CLK / 12 ) / ( BAUD_RATE * HITS );  //此公式值得你琢磨一下

TH2 = RCAP2H;

TL2 = RCAP2L;

ET2 = 1;

TR2 = 1;

EA = 1;

}

//接收初始化

extern void RXD_init()

{

unsigned char i;

RXD_pin = 1;

RXD_p1 = 0;

RXD_p2 = 0;

for ( i=0; i

{

RXD_buf[i] = 0x00;

}

}

//发送初始化

extern void TXD_init()

{

unsigned char i;

TXD_pin = 1;

TXD_p1 = 0;

TXD_p2 = 0;

for ( i=0; i< TXD_BUF_LEN; i++ )

{

TXD_buf[i] = 0x00;

}

}

//发送单个字符

extern void TXD_Send_Char(const unsigned char c)

{

unsigned char p;  //临时变量

p = TXD_p1 + 1;

if ( p >= TXD_BUF_LEN ) p = 0;

while ( p == TXD_p2 );  //判断发送缓冲队列是否已满,如果是,则暂时不能发送

TXD_buf[TXD_p1] = c;  //先将c写入队列

TXD_p1 = p;  //再修改TXD_p1

//在T2中断服务程序里会自动完成发送

}

//发送字符串(不包括末尾的'\0')

extern void TXD_Send_String(const unsigned char s[])

{

unsigned char c;

unsigned int i = 0;

for (;;)

{

c = s[i++];

if ( c == '\0' ) break;

TXD_Send_Char(c);

}

}

//定义接收缓冲字符

volatile unsigned char bdata RXD_ch;

sbit RXD_ch_MSB = RXD_ch^7;

//定义发送缓冲字符

volatile unsigned char bdata TXD_ch;

sbit TXD_ch_LSB = TXD_ch^0;

//T2中断服务程序

//每中断HITS次处理1位

static void T2INTSVC() interrupt 5 using 3

{

//定义接收所需要的变量

static bit RXD_doing = 0;  //正在接收的标志

static unsigned char RXD_t = HITS/2;  //接收时计数T2的中断次数

static unsigned char RXD_cnt;  //接收时bit位的计数器

//定义发送所需要的变量

static bit TXD_doing = 0;  //正在发送的标志

static unsigned char TXD_t;  //发送时计数T2的中断次数

static unsigned char TXD_cnt;  //发送时bit位的计数器

//先清除TF2

TF2 = 0;

//接收数据

if ( RXD_doing )  //正处于接收状态

{

if ( --RXD_t == 0 )  //经过了HITS个采样脉冲

{

if ( RXD_cnt == 0 )  //8个数据位接收完毕

{

if ( RXD_pin )  //检测到停止位

{

RXD_t = RXD_p1 + 1;  //在这里,RXD_t作为临时变量

if ( RXD_t >= RXD_BUF_LEN ) RXD_t = 0;

if ( RXD_t != RXD_p2 )  //如果接收缓冲队列未满

{

RXD_buf[RXD_p1] = RXD_ch;

RXD_p1 = RXD_t;

}

else

{

//如果接收缓冲队列已满,只好丢弃新收到数据

}

}

else  //检测停止位时出错

{

//舍弃新收到的数据

}

RXD_doing = 0;  //接收全部完毕,清除正在接收的标志

RXD_t = HITS/2;  //恢复RXD_t的初始值

}

else  //接收数据位

{

RXD_ch >>= 1;

RXD_ch_MSB = RXD_pin;

//上面2条语句若用{CY=RXD_pin; CY=(RXD_ch&0x01); RXD_ch=ACC;}代替,效率更高

RXD_cnt--;

RXD_t = HITS;

}

}

}

else  //检测起始位

{

if ( RXD_pin )

{

RXD_t = HITS/2;

}

else

{

RXD_t--;

if ( RXD_t == 0 )  //连续HITS/2次采样RXD_pin都是0,就可以确认起始位

{

//启动接收

RXD_t = HITS;

RXD_cnt = 8;

RXD_doing = 1;

}

}

}

//发送数据

if ( TXD_doing )  //正处于发送状态

{

TXD_t--;

if ( TXD_t == 0 )

{

if ( TXD_cnt == 0 )  //发送全部完毕

{

TXD_doing = 0;  //清除正在发送的标志

}

else

{

if ( TXD_cnt == 1 )  //8个数据位发送完毕

{

TXD_pin = 1;  //发送停止位

}

else  //发送数据位

{

TXD_pin = TXD_ch_LSB;

TXD_ch >>= 1;

//上面2条语句若用{CY=(TXD_ch&0x01); TXD_pin=CY; TXD_ch=ACC;}代替,效率更高

}

TXD_cnt--;

TXD_t = HITS;

}

}

}

else

{

if ( TXD_p2 != TXD_p1 )  //如果发送缓冲队列不空

{

//从发送缓冲队列中取出要发送的数据

TXD_ch = TXD_buf[TXD_p2++];

if ( TXD_p2 >= TXD_BUF_LEN ) TXD_p2 = 0;

//启动发送

TXD_doing = 1;

TXD_cnt = 9;

TXD_t = HITS;

//先发送起始位

TXD_pin = 0;

}

else

{

//发送缓冲队列是空的,不发送任何数据

}

}

}

//系统初始化

void SystemInit()

{

TXD_init();

RXD_init();

T2_init();

}

//主程序

void main()

{

unsigned char c;

SystemInit();

//

TXD_Send_String("Hello!\r\n");

TXD_Send_String("The author is 21IC suda.\r\n");

//以下是简单的测试:从接收引脚接收数据,再通过发送引脚转发出去

for (;;)

{

if ( RXD_p2 != RXD_p1 )

{

c = RXD_buf[RXD_p2++];

if ( RXD_p2 >= RXD_BUF_LEN ) RXD_p2 = 0;

TXD_Send_Char(c);

}

}

}

答 1:

留下来看看

答 2:

几年前我就用了现在不用了,改用16550扩展,不跟它扯了,要做就做结实的东西

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值