c语言串口通讯发射用IO口模拟,使用单片机普通IO口模拟串口的三种方法

随着单片机的使用日益频繁,用其作前置机进行采集和通信也常见于各种应用,一般是利用前置

机采集各种终端数据后进行处理、存储,再主动或被动上报给管理站。这种情况下下,采集会需

要一个串口,上报又需要另一个串口,这就要求单片机具有双串口的功能,但我们知道一般的51

系列只提供一个串口,那么另一个串口只能靠程序模拟。

本文所说的模拟串口, 就是利用51的两个输入输出引脚如P1.0和P1.1,置1或0分别代表高低电

平,也就是串口通信中所说的位,如起始位用低电平,则将其置0,停止位为高电平,则将其置

1,各种数据位和校验位则根据情况置1或置0。至于串口通信的波特率,说到底只是每位电平持续

的时间,波特率越高,持续的时间越短。如波特率为9600BPS,即每一位传送时间为

1000ms/9600=0.104ms,即位与位之间的延时为为0.104毫秒。单片机的延时是通过执行若干条

指令来达到目的的,因为每条指令为1-3个指令周期,可即是通过若干个指令周期来进行延时的,

单片机常用11.0592M的的晶振,现在我要告诉你这个奇怪数字的来历。用此频率则每个指令周期

的时间为(12/11.0592)us,那么波特率为9600BPS每位要间融多少个指令周期呢?

指令周期s=(1000000/9600)/(12/11.0592)=96,刚好为一整数,如果为4800BPS则为

96x2=192,如为19200BPS则为48,别的波特率就不算了,都刚好为整数个指令周期,妙吧。至于

别的晶振频率大家自已去算吧。

现在就以11.0592M的晶振为例,谈谈三种模拟串口的方法。

方法一:延时法

通过上述计算大家知道,串口的每位需延时0.104秒,中间可执行96个指令周期。

#define uchar unsigned char

sbit P1_0 = 0x90;

sbit P1_1 = 0x91;

sbit P1_2 = 0x92;

#define RXD P1_0

#define TXD P1_1

#define WRDYN 44 //写延时

#define RDDYN 43 //读延时

//往串口写一个字节

void WByte(uchar input)

{

uchar i=8;

TXD=(bit)0; //发送启始

Delay2cp(39);

//发送8位数据位

while(i--)

{

TXD=(bit)(input&0x01); //先传低位

Delay2cp(36);

input=input>>1;

}

//发送校验位(无)

TXD=(bit)1; //发送结束

Delay2cp(46);

}

//从串口读一个字节

uchar RByte(void)

{

uchar Output=0;

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,以下是一个简单的STC单片机串口通信协议解析的C语言代码: ```c #include <STC15F2K60S2.h> typedef unsigned char uint8_t; typedef unsigned int uint16_t; #define BUF_LEN 20 // 接收缓冲区 volatile uint8_t buffer[BUF_LEN]; // 缓冲区指针 volatile uint8_t buf_ptr = 0; // 解析状态 volatile uint8_t parse_state = 0; // 数据长度 volatile uint8_t data_len = 0; // 命令字 volatile uint8_t cmd = 0; // 数据 volatile uint8_t data[BUF_LEN]; // 串口接收中断服务程序 void uart_isr() __interrupt 4 { uint8_t ch = SBUF; // 读取接收到的数据 switch(parse_state) { case 0: // 等待头部 if(ch == 0xAA) { parse_state = 1; } break; case 1: // 解析头部 data_len = ch; cmd = SBUF; buf_ptr = 0; parse_state = 2; break; case 2: // 接收数据 buffer[buf_ptr++] = ch; if(buf_ptr >= data_len) { parse_state = 3; } break; case 3: // 校验数据 if(ch == 0x55) { // 处理数据 handle_data(cmd, data, data_len); } parse_state = 0; break; default: parse_state = 0; break; } } // 处理数据 void handle_data(uint8_t cmd, uint8_t* data, uint8_t len) { // 根据命令和数据进行处理 switch(cmd) { case 0x01: // 读取Flash // ... break; case 0x02: // 写入Flash // ... break; case 0x03: // 读取IO // ... break; case 0x04: // 写入IO // ... break; default: break; } // 回复数据 // ... } // 串口初始化 void uart_init() { PCON |= 0x80; SCON = 0x50; AUXR |= 0x40; TMOD &= 0x0F; TMOD |= 0x20; TH1 = 0xFD; TL1 = TH1; TR1 = 1; ES = 1; EA = 1; } int main() { uart_init(); // 初始化串口 while(1) { // 主程序代码 // ... } return 0; } ``` 该代码中,使用了一个大小为20的接收缓冲区,当接收到数据时,中断服务程序将数据存储在接收缓冲区中。通过解析接收缓冲区中的数据,可以获取到数据的长度、命令和实际数据等信息。根据命令和数据进行处理后,可以向发送方回复数据。需要根据具体的通信协议进行相应的修改。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值