单片机IO口模拟串口程序(发送+接收)
STC单片机虚拟串口发送程序(超简单)
![STC单片机虚拟串口发送程序(超简单)](https://img.taocdn.com/s3/m/eb22c5423a3567ec102de2bd960590c69ec3d8d7.png)
STC单片机虚拟串口发送程序(超简单)STC单片机(STC12C5A32S)虚拟串口发送程序//虚拟串口发送子函数void Uart(uint8 a){ACC=a; //TXD3是已经定义的任意的发送端口TR1=1;TXD3=0; //发送起始位while(TF1==0);TF1=0; //TF1必须清零,因为只有启用T1中断才会自动清零TXD3=ACC0; //发送8个位也可以用移位来发送,ACC0-ACC7也必须先定义while(TF1==0); //表示ACC的8个位,如果用移位发送,就不用这样定义。
TF1=0;TXD3=ACC1;while(TF1==0);TF1=0;TXD3=ACC2;while(TF1==0);TF1=0;TXD3=ACC3;while(TF1==0);TF1=0;TXD3=ACC4;while(TF1==0);TF1=0;TXD3=ACC5;while(TF1==0);TF1=0;TXD3=ACC6;while(TF1==0);TF1=0;TXD3=ACC7;while(TF1==0);TF1=0;TXD3=1; //发送停止位while(TF1==0);TF1=0;TR1=0;}该子函数使用T1定时器,T0也可以。
采用8位自动重装,重装值为A0Main(){TMOD = 0x21; //T0:模式1,16位定时器。
T1:模式2,8位定时器,自动重装AUXR &= 0x3f; //定时器0和定时器1与普通8051定时器一样(不同的单片机设置可能不同)TL1 = 0xa0; //虚拟串口波特率:9600TH1 = 0xa0;ET0 = 1;ET1 = 0; //T1中断一定不要使用,要不接收会错误TR0 = 1;TR1 = 0;Uart(0xaa); //0xaa是发送的数据,如果接收有误,在发送一个字节后可加点延时//延时While(1); //具体程序此处省略}注:因本人实验的硬件不需要模拟串口来接收数据,故没给出虚拟串口接收程序。
串口发送和接收数据的一般方法
![串口发送和接收数据的一般方法](https://img.taocdn.com/s3/m/0726edc9d1d233d4b14e852458fb770bf78a3ba2.png)
串口发送和接收数据的一般方法串口通信是一种用于在计算机或嵌入式系统之间传输数据的常用通信方式。
它使用串行连接,并遵循一定的通信协议。
在串口通信中,通常涉及到发送和接收数据的步骤。
下面是串口发送和接收数据的一般方法的详细解释。
1.打开串口:在发送和接收数据之前,需要首先打开串口连接。
打开串口可以通过相应的串口库函数实现。
常用的串口库函数有SerialPort in C/C++和pyserial in Python。
这些库函数提供了用于打开和控制串口的功能。
2.配置串口参数:打开串口后,需要配置一些串口参数,例如波特率、数据位、停止位和校验位等。
这些参数的配置通常由串口库函数提供的设置函数完成。
根据实际需求,可以选择不同的参数配置。
3.发送数据:发送数据是通过调用串口库函数提供的发送函数实现的。
发送函数通常需要传入一个数据缓冲区和要发送的数据长度作为参数。
在发送数据之前,需要将要发送的数据存储到数据缓冲区中。
发送函数会将数据从缓冲区发送到串口。
4.接收数据:接收数据是通过调用串口库函数提供的接收函数实现的。
接收函数通常需要传入一个数据缓冲区和要接收的数据长度作为参数。
在接收数据之前,需要定义一个足够大的缓冲区来存储接收到的数据。
接收函数会将数据从串口读取并存储到缓冲区中。
5.数据处理:接收到的数据可以进行进一步的处理。
例如,可以将数据解析为具体的信息,或者根据接收到的数据执行特定的操作。
数据处理的方法取决于应用需求。
6.关闭串口:在数据的发送和接收任务完成之后,应该关闭串口连接。
关闭串口可以通过调用串口库函数提供的关闭函数实现。
关闭串口将释放相关的资源。
需要注意的是,在进行串口通信时,要确保发送和接收端的串口参数配置一致。
否则,可能导致通信失败或数据解析错误。
上述是关于串口发送和接收数据的一般方法的基本介绍。
具体的实现方法和细节会因为不同的编程语言和串口库函数而有所差异。
因此,在实际应用中可以根据具体情况选择适合的编程语言和库函数,以实现串口通信。
51单片机串口通信(相关例程)
![51单片机串口通信(相关例程)](https://img.taocdn.com/s3/m/3abd742df08583d049649b6648d7c1c708a10b97.png)
51单片机串口通信(相关例程) 51单片机串口通信(相关例程)一、简介51单片机是一种常用的微控制器,它具有体积小、功耗低、易于编程等特点,被广泛应用于各种电子设备和嵌入式系统中。
串口通信是51单片机的常见应用之一,通过串口通信,可以使单片机与其他外部设备进行数据交互和通信。
本文将介绍51单片机串口通信的相关例程,并提供一些实用的编程代码。
二、串口通信基础知识1. 串口通信原理串口通信是通过串行数据传输的方式,在数据传输过程中,将信息分为一个个字节进行传输。
在51单片机中,常用的串口通信标准包括RS232、RS485等。
其中,RS232是一种常用的串口标准,具有常见的DB-9或DB-25连接器。
2. 串口通信参数在进行串口通信时,需要设置一些参数,如波特率、数据位、停止位和校验位等。
波特率表示在单位时间内传输的比特数,常见的波特率有9600、115200等。
数据位表示每个数据字节中的位数,一般为8位。
停止位表示停止数据传输的时间,常用的停止位有1位和2位。
校验位用于数据传输的错误检测和纠正。
三、串口通信例程介绍下面是几个常见的51单片机串口通信的例程,提供给读者参考和学习:1. 串口发送数据```C#include <reg51.h>void UART_Init(){TMOD = 0x20; // 设置计数器1为工作方式2(8位自动重装) TH1 = 0xFD; // 设置波特率为9600SCON = 0x50; // 设置串口工作方式1,允许串行接收TR1 = 1; // 启动计数器1}void UART_SendChar(unsigned char dat){SBUF = dat; // 发送数据while (!TI); // 等待发送完成TI = 0; // 清除发送完成标志}void main(){UART_Init(); // 初始化串口while (1){UART_SendChar('A'); // 发送字母A}}```2. 串口接收数据```C#include <reg51.h>void UART_Init(){TMOD = 0x20; // 设置计数器1为工作方式2(8位自动重装) TH1 = 0xFD; // 设置波特率为9600SCON = 0x50; // 设置串口工作方式1,允许串行接收TR1 = 1; // 启动计数器1}void UART_Recv(){unsigned char dat;if (RI) // 检测是否接收到数据{dat = SBUF; // 读取接收到的数据 RI = 0; // 清除接收中断标志// 处理接收到的数据}}void main(){UART_Init(); // 初始化串口EA = 1; // 允许中断ES = 1; // 允许串口中断while (1)// 主循环处理其他任务}}```3. 串口发送字符串```C#include <reg51.h>void UART_Init(){TMOD = 0x20; // 设置计数器1为工作方式2(8位自动重装) TH1 = 0xFD; // 设置波特率为9600SCON = 0x50; // 设置串口工作方式1,允许串行接收TR1 = 1; // 启动计数器1}void UART_SendString(unsigned char *str){while (*str != '\0')SBUF = *str; // 逐个发送字符while (!TI); // 等待发送完成TI = 0; // 清除发送完成标志str++; // 指针指向下一个字符}}void main(){UART_Init(); // 初始化串口while (1){UART_SendString("Hello, World!"); // 发送字符串}}```四、总结本文介绍了51单片机串口通信的基础知识和相关编程例程,包括串口发送数据、串口接收数据和串口发送字符串。
IO口模拟UART串口通信
![IO口模拟UART串口通信](https://img.taocdn.com/s3/m/d14ce51c974bcf84b9d528ea81c758f5f61f2954.png)
IO口模拟UART串口通信为了让大家充分理解UART串口通信的原理,我们先用P3.0和P3.1这两个当做IO口来开展模拟实际串口通信的过程,原理搞懂后,我们再使用存放器配置实现串口通信过程。
对于UART串口波特率,常用的值是300、600、1200、2400、4800、9600、14400、19200、28800、38400、57600、115200、128000、256000等速率。
IO口模拟UART串行通信程序是一个简单的演示程序,我们使用串口调试助手下发一个数据,数据加1后,再自动返回。
串口调试助手,在我们开展全板子测试视频的时候,大家已经见过,这里我们直接使用STC-ISP软件自带的串口调试助手,先把串口调试助手使用给大家说一下,如图1所示。
第一步要选择串口助手菜单,第二步选择十六进制显示,第三步选择十六进制发送,第四步选择COM口,这个COM口要和自己电脑设备管理器里的那个COM口一致,波特率是我们程序设定好的选择,我们程序中让一个数据位持续时间是1/9600秒,那这个地方选择波特率就是选9600,校验位选N,数据位8,结束位1。
图1串口调试助手示意图串口调试助手的实质就是我们利用电脑上的UART通信接口,通过这个UART接口发送数据给我们的单片机,也可以把我们的单片机发送的数据接收到这个调试助手界面上。
因为初次接触通信方面的技术,所以我对这个程序开展一下解释,大家可以边看我的解释边看程序,把底层原理先彻底弄懂。
变量定义部分就不用说了,直接看main主函数。
首先是对通信的波特率的设定,在这里我们配置的波特率是9600,那么串口调试助手也得是9600。
配置波特率的时候,我们用的是定时器0的模式2。
模式2中,不再是TH0代表高8位,TL0代表低8位了,而只有TL0在开展计数了。
当TL0溢出后,不仅仅会让TF0变1,而且还会将TH0中的内容重新自动装到TL0中。
这样有一个好处,我们可以把我们想要的定时器初值提前存在TH0中,当TL0溢出后,TH0自动把初值就重新送入TL0了,全自动的,不需要程序上再给TL0重新赋值了,配置方式很简单,大家可以自己看下程序并且计算一下初值。
51单片机IO口模拟串口
![51单片机IO口模拟串口](https://img.taocdn.com/s3/m/358455cf6137ee06eff91891.png)
论坛新老朋友们。
祝大家新年快乐。
在新的一年开始的时候,给大家一点小小的玩意。
工程师经常碰到需要多个串口通信的时候,而低端单片机大多只有一个串行口,甚至没有串口。
这时候无论是选择高端芯片,还是更改系统设计都是比较麻烦的事。
我把以前搞的用普通I/O口模拟串行口通讯的程序拿出来,供大家参考,希望各位兄弟轻点拍砖。
基本原理:我们模拟的是串行口方式1.就是最普通的方式。
一个起始位、8个数据位、一个停止位。
模拟串行口最关键的就是要计算出每个位的时间。
以波特率9600为例,每秒发9600个位,每个位就是1/9600秒,约104个微秒。
我们需要做一个精确的延时,延时时间+对IO口置位的时间=104微秒。
起始位是低状态,再延时一个位的时间。
停止位是高状态,也是一个位的时间。
数据位是8个位,发送时低位先发出去,接收时先接低位。
了解这些以后,做个IO 模拟串口的程序,就是很容易的事。
我们开始。
先上简单原理图:就一个MAX232芯片,没什么好说的,一看就明白。
使用单片机普通I/O口,232数据输入端使用51单片机P3.2口(外部中断1口,接到普通口上也可以,模拟中断方式的串行口会有用。
呵呵)。
数据输出为P0.4(随便哪个口都行)。
下面这个程序,您只需吧P0.4 和P3.2 当成串口直接使用即可,经过测试完全没有问题. 2、底层函数代码如下:sbit TXD1 = P0^4; //定义模拟输出脚sbit RXD1 = P3^2; //定义模拟输入脚bdata unsigned char SBUF1; //定义一个位操作变量sbit SBUF1_bit0 = SBUF1^0;sbit SBUF1_bit1 = SBUF1^1;sbit SBUF1_bit2 = SBUF1^2;sbit SBUF1_bit3 = SBUF1^3;sbit SBUF1_bit4 = SBUF1^4;sbit SBUF1_bit5 = SBUF1^5;sbit SBUF1_bit6 = SBUF1^6;sbit SBUF1_bit7 = SBUF1^7;void delay_bps() {unsigned char i; for (i = 0; i < 29; i++); _nop_();_nop_();} //波特率9600 模拟一个9600波特率unsigned char getchar2() //模拟接收一个字节数据{while (RXD1);_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();delay_bps();SBUF1_bit0 = RXD1; //0delay_bps();SBUF1_bit1 = RXD1; //1delay_bps();SBUF1_bit2 = RXD1; //2delay_bps();SBUF1_bit3 = RXD1; //3delay_bps();SBUF1_bit4 = RXD1; //4delay_bps();SBUF1_bit5 = RXD1; //5delay_bps();SBUF1_bit6 = RXD1; //6delay_bps();SBUF1_bit7 = RXD1; //7delay_bps();return(SBUF1) ; //返回读取的数据}void putchar2(unsigned char input) //模拟发送一个字节数据{SBUF1 = input;TXD1 = 0; //起始位delay_bps();TXD1 = SBUF1_bit0; //0delay_bps();TXD1 = SBUF1_bit1; //1delay_bps();TXD1 = SBUF1_bit2; //2delay_bps();TXD1 = SBUF1_bit3; //3delay_bps();TXD1 = SBUF1_bit4; //4delay_bps();TXD1 = SBUF1_bit5; //5delay_bps();TXD1 = SBUF1_bit6; //6delay_bps();TXD1 = SBUF1_bit7; //7delay_bps();TXD1 = 1; //停止位delay_bps();}3、实现串行通讯。
51单片机串口通信连续发送接收字节
![51单片机串口通信连续发送接收字节](https://img.taocdn.com/s3/m/4199656b326c1eb91a37f111f18583d048640f42.png)
51单片机串口通信连续发送接收字节51单片机串口通信连续发送接收字节当使用单片机串口通信,连续发送字节时,如何处理呢?使用串口中断接收发送字节,中断内的程序尽可能简单,因为考虑到占用时间。
本文以连续发送4个字节为例,给出例程如下所示:本例程使用的单片机型号为:IAP15W4K58S//工作频率为11.0592MHz#include "reg51.h"#include "intrins.h"typedef unsigned char BYTE;typedef unsigned int WORD;#define FOSC 11059200L //系统频率//#define BAUD 115200 //#define BAUD 9600 //定义串口波特率#define Num_byte 4 //接收数据4个字节BYTE Data_temp[Num_byte]={0,0,0,0};sfr P0M1 = 0x93;sfr P0M0 = 0x94;sfr P1M1 = 0x91;sfr P1M0 = 0x92;sfr P2M1 = 0x95;sfr P2M0 = 0x96;sfr P3M1 = 0xb1;sfr P3M0 = 0xb2;sfr P4M1 = 0xb3;sfr P4M0 = 0xb4;sfr P5M1 = 0xC9;sfr P5M0 = 0xCA;sfr P6M1 = 0xCB;sfr P6M0 = 0xCC;sfr P7M0 = 0xE2;sfr AUXR = 0x8e; //辅助寄存器sfr T2H = 0xd6; //定时器2高8位sfr T2L = 0xd7; //定时器2低8位sfr P_SW1 = 0xA2; //外设功能切换寄存器1sbit LED1=P1^1;sbit LED2=P1^2;bit busy=0; //定义是否接收完4个字节BYTE num=0; //记录4个字节的数据void SendData(BYTE dat);void SendString(char *s);BYTE read_Byte();void delay();void main(){P0M0 = 0x00;P0M1 = 0x00;P1M0 = 0x00;P1M1 = 0x00;P2M0 = 0x00;P2M1 = 0x00;P3M0 = 0x00;P3M1 = 0x00;P4M0 = 0x00;P4M1 = 0x00;P5M0 = 0x00;P5M1 = 0x00;P6M0 = 0x00;P7M0 = 0x00;P7M1 = 0x00;P_SW1 &= 0x3F; //(P3.0/RxD, P3.1/TxD)SCON = 0x50; //8位可变波特率,允许接收T2L = (65536 - (FOSC/4/BAUD)); //设置波特率重装值T2H = (65536 - (FOSC/4/BAUD))>>8;AUXR = 0x15; //T2为1T模式, 并启动定时器2,选择定时器2为串口1的波特率发生器ES = 1; //使能串口1中断EA = 1;//SendString("STC15F2K60S2\r\nUart Test !\r\n");while(1){if(busy){ES=0;for(num=0;num<num_byte;num++)< p="">{SBUF= Data_temp[num]+0x05;while(!TI);TI=0;}num=0;ES=1;busy=0;}//SendData(3);//delay();//delay();;}/*----------------------------UART 中断服务程序-----------------------------*/void Uart() interrupt 4 using 1{ES=0;RI = 0; //清除RI位Data_temp[num++]= SBUF;if(num==Num_byte)busy=1;ES=1;}/*----------------------------发送串口数据----------------------------*/void SendData(BYTE dat){while (busy); //等待前面的数据发送完成SBUF = dat; //写数据到SBUF寄存器busy = 1;}/*----------------------------发送字符串----------------------------*/void SendString(char *s){while (*s) //检测字符串结束标志{SendData(*s); //发送当前字符s++;}//接收1个字节BYTE read_Byte(){ BYTE character; character = SBUF; return character;}void delay(){ BYTE i,j;for(i=220;i--;i>0)for(j=220;j--;j>0); }</num_byte;num++)<>。
单片机串行口接收和发送数据的过程简述
![单片机串行口接收和发送数据的过程简述](https://img.taocdn.com/s3/m/61b33a0ea32d7375a41780ce.png)
单片机串行口接收和发送数据的过程简述
串行口接收和发送数据的过程简述
答:在发送过程中,当执行一条将数据写入发送缓冲器SBUF(99H)的指令时,串行口把SBUF中8位数据以fosc/l2的波特率从RXD(P3.0)端输出,发送完毕置中断标志TI=1。
写SBUF指令在S6P1处产生一个正脉冲,在下一个机器周期的S6P2处,数据的最低位输出到RXD(P3.0)脚上;再在下一个机器周期的S3、S4和S5输出移位时钟为低电平时,在S6及下一个机器周期的Sl和S2为高电平,就这样将8位数据由低位至高位一位一位顺序通过RXD线输出。
并在TXD脚上输出fosc/12的移位时钟。
在写SBUF有效后的第10个机器周期的SlPl将发送中断标志TI置位。
接收时,用软件置REN=1(同时,RI=0),即开始接收。
当使SCON中的REN=1(RI=0)时,产生一个正的脉冲,在下一个机器周期的S3P1~S5P2,从TXD(P3.1)脚上输出低电平的移位时钟,在此机器周期的S5P2对P3.0脚采样.并在本机器周期的S6P2通过串行口内的输入移位寄存器将采样值移位接收。
在同一个机器周期的S6P1到下一个机器周期的S2P2,输出移位时钟为高电平。
于是,将数据字节从低位至高位接收下来并装入SBUF。
在启动接收过程(即写SCON,清RI位),将SCON中的RI清0之后的第l0个机器周期的SlPl将RI置位。
这一帧数据接收完毕,可进行下一帧接收。
STM8L101F3P6单片机IO模拟收发调试
![STM8L101F3P6单片机IO模拟收发调试](https://img.taocdn.com/s3/m/5a9552207375a417866f8fb4.png)
本程序选用的芯片为STM8L101F3P6共分为如下几个文件Main.c文件内容#include "stm8l10x_diy_time.h"#include "stm8l10x_diy_port.h"#include "STM8L101F3P.h"#include "NRF24L01.h"#include "STM8l10x.h"char lock_key;void main(void){clk_init ();//时钟初始化gpio_init();time_init();LED01=0;LED02=0;IRQ_OUT;//IRQ设置为输出模式IRQ_O=1;//赋值ifnnrf_rx_mode();while (1){if(But01==0){ IRQ_OUT;IRQ_O=1;SPI_RW_Reg(WRITE_REG+STATUS,0xff);tx_buf[0]=2;ifnnrf_tx_mode();IRQ_IN;while(IRQ_I);sta=SPI_Read(STATUS);SPI_RW_Reg(WRITE_REG+STA TUS,0xff);if(sta& STA_MARK_TX){LED02=1;Delay(0xfffFf);LED02=0;Delay(0xffFff);}else{ifnnrf_CLERN_ALL();LED02=1;Delay(0xffFf);LED02=0;Delay(0xffFf);}ifnnrf_rx_mode();IRQ_OUT;IRQ_O=1;IRQ_IN;Delay(0x0f);while(IRQ_I==0);Delay(0xffff);}IRQ_OUT;IRQ_O=1;IRQ_IN;if(IRQ_I==0){sta=SPI_Read(STATUS);SPI_RW_Reg(WRITE_REG+STATUS,0xff);if(sta&STA_MARK_RX){SPI_Read_Buf(RD_RX_PLOAD,rx_buf,TX_PLOAD_WIDTH);if (rx_buf[0] == 2){LED01=1;Delay(0xffFff);LED01=0;Delay(0xfFfff);rx_buf[0] = 0;}}else{ifnnrf_CLERN_ALL();ifnnrf_rx_mode();IRQ_OUT;IRQ_O=1;IRQ_IN;Delay(0x0f);while(IRQ_I==0);}}}}@far @interrupt void TIM4_interrupt(void){static unsigned int TIM_Work;static unsigned char TIM_Time;if(But01==0){if(TIM_Work++>2500){// LED01 =~LED01;TIM_Work=0;}}else{TIM_Work =0;// LED01 =0;}TIM4_SR1 = 0x00;return;}stm8_interrupt_vector.c内容/* BASIC INTERRUPT VECTOR TABLE FOR STM8 devices* Copyright (c) 2007 STMicroelectronics*/typedef void @far (*interrupt_handler_t)(void);struct interrupt_vector {unsigned char interrupt_instruction;interrupt_handler_t interrupt_handler;};@far @interrupt void NonHandledInterrupt(void){/* in order to detect unexpected events during development, it is recommended to set a breakpoint on the following instruction */return;}extern void _stext(); /* startup routine */extern @far @interrupt void TIM4_interrupt(void);struct interrupt_vector const _vectab[] = {{0x82, (interrupt_handler_t)_stext}, /* reset */{0x82, NonHandledInterrupt}, /* trap */{0x82, NonHandledInterrupt}, /* irq0 */{0x82, NonHandledInterrupt}, /* irq1 */{0x82, NonHandledInterrupt}, /* irq2 */{0x82, NonHandledInterrupt}, /* irq3 */{0x82, NonHandledInterrupt}, /* irq4 */{0x82, NonHandledInterrupt}, /* irq5 */{0x82, NonHandledInterrupt}, /* irq6 */{0x82, NonHandledInterrupt}, /* irq7 */{0x82, NonHandledInterrupt}, /* irq8 */{0x82, NonHandledInterrupt}, /* irq9 */{0x82, NonHandledInterrupt}, /* irq10 */{0x82, NonHandledInterrupt}, /* irq11 */{0x82, NonHandledInterrupt}, /* irq12 */{0x82, NonHandledInterrupt}, /* irq13 */{0x82, NonHandledInterrupt}, /* irq14 */{0x82, NonHandledInterrupt}, /* irq15 */{0x82, NonHandledInterrupt}, /* irq16 */{0x82, NonHandledInterrupt}, /* irq17 */{0x82, NonHandledInterrupt}, /* irq18 */{0x82, NonHandledInterrupt}, /* irq19 */{0x82, NonHandledInterrupt}, /* irq20 */{0x82, NonHandledInterrupt}, /* irq21 */{0x82, NonHandledInterrupt}, /* irq22 */{0x82, NonHandledInterrupt}, /* irq23 */{0x82, NonHandledInterrupt}, /* irq24 */{0x82, TIM4_interrupt}, /* irq25 */{0x82, NonHandledInterrupt}, /* irq26 */{0x82, NonHandledInterrupt}, /* irq27 */{0x82, NonHandledInterrupt}, /* irq28 */{0x82, NonHandledInterrupt}, /* irq29 */};stm8l10x_diy_port.c内容#include "stm8l10x_diy_port.h"#include "STM8L101F3P.h"#include "stm8l10x_gpio.h"/************************************************************** 功能:配置IO口配置IO输入输出说明输出:配置PC_DDR,PC_CR1寄存器,把相应位拉高即可输入:只配置PD_CR1寄存器,拉高即可/*************************************************************/ void gpio_init(void){GPIO_DeInit(GPIOB);//恢复寄存器到默认值GPIO_DeInit(GPIOC);GPIO_DeInit(GPIOD);/*配置输出****************************************************/ PC_DDR|= 0x04;//LEDPC_CR1|= 0x04;//LEDPD_DDR|= 0x01;//LEDPD_CR1|= 0x01;//LEDPC_DDR|= 0x01;//CEPC_CR1|= 0x01;//CEPB_DDR|= 0x10;//CSNPB_CR1|= 0x10;//CSNPB_DDR|= 0x20;//SCKPB_CR1|= 0x20;//SCKPB_DDR|= 0x80;//MISOPB_CR1|= 0x80;//MISO/*配置输入****************************************************/ PC_CR1|= 0x08;//buttomPB_CR1|= 0x01;//buttomPB_CR1|= 0x40;//mOSIPB_CR1|= 0x02;//IRQLED01=1;LED02=1;IRQ_OUT;//IRQ作为输出IRQ_O=1;CE=0; // chip enableCSN=1; // Spi disableSCK=0; // Spi clock line init high}/************************************************************** 功能:配置时钟/*************************************************************/ void clk_init(void){CLK_CKDIVR = 0x00;CLK_PCKENR|= 0x04;//开启定时器4中断(必修有)/*TIM2:0x01TIM3:0x02TIM4:0x04************************************************************/}/************************************************************** 延迟函数/*************************************************************/ void Delay(unsigned int nCount){while (nCount != 0){nCount--;}}/************************************************************** 按键防抖动及按键锁/*************************************************************/ char Key_Scanf(char Buttom){static char Key_Lock;char ButtomStatus;ButtomStatus=But_OFF ;if(Buttom==But_ON){Delay(0x3ff);/* 消抖*/if((Buttom==But_ON)&&(Key_Lock==1)){ButtomStatus=But_ON;}}else Key_Lock= 1;return ButtomStatus;}stm8l10x_diy_port.h内容#ifndef __stm8l10x_diy_port_H#define __stm8l10x_diy_port_H#include "STM8L101F3P.h"#define L 0#define H 1#define But_ON 0 //按下时为低#define But_OFF 1#define IRQ_OUT PB_DDR|= 0x02 //配置输出#define IRQ_IN PB_DDR&= 0xFD //配置输入_Bool IRQ_O @PB_ODR:1;//IRQ输出。
51单片机模拟串口的三种方法
![51单片机模拟串口的三种方法](https://img.taocdn.com/s3/m/9471d39acf2f0066f5335a8102d276a2002960e7.png)
51单片机模拟串口的三种方法单片机模拟串口是指通过软件实现的一种串口通信方式,主要应用于一些资源有限的场合,如单片机中没有硬件UART模块的情况下。
下面将介绍三种常用的单片机模拟串口的方法。
1.轮询法轮询法是最简单的一种模拟串口方法,其原理是通过轮询方式不断查询接收和发送的数据。
在接收数据时,单片机通过忙等待的方式查询接收端是否有数据到达,并且处理数据。
在发送数据时,单片机通过检查发送端是否空闲,然后发送数据。
这种方法的优点是实现简单,占用资源少。
缺点是轮询过程可能会浪费一定的时间,同时由于忙等待可能会占用CPU资源,影响其他任务的执行。
2.中断法中断法是一种基于中断机制实现的模拟串口方法,其原理是通过外部中断或定时器中断触发,单片机响应中断并进行串口数据的接收和发送。
在接收数据时,单片机通过外部中断或定时器中断来检测串口接收中断,并处理接收到的数据;在发送数据时,单片机通过定时器中断来定时发送数据。
这种方法的优点是能够及时响应串口的数据接收和发送,不会浪费过多的时间。
缺点是中断处理可能会占用一定的CPU资源,同时中断嵌套可能会引起一些问题。
3.环形缓冲法环形缓冲法是一种基于环形缓冲区的模拟串口方法,其原理是通过环形缓冲区来缓存接收和发送的数据。
在接收数据时,单片机将串口接收到的数据放入环形缓冲区,并使用指针指示当前读取位置和写入位置,然后通过轮询或中断方式从缓冲区中读取数据并进行处理;在发送数据时,单片机将要发送的数据放入环形缓冲区,并通过轮询或中断方式从缓冲区中读取数据并发送。
这种方法的优点是能够有效地处理串口数据的接收和发送,不会浪费过多的时间,并且能够缓存一定量的数据。
缺点是需要额外的缓冲区,占用一定的内存空间。
综上所述,通过轮询法、中断法和环形缓冲法三种方法,可以实现单片机的串口模拟功能。
根据实际需求,选择合适的方法来实现串口通信。
STC51单片机普通IO口模拟IIC(I2C)接口通讯的程序代码
![STC51单片机普通IO口模拟IIC(I2C)接口通讯的程序代码](https://img.taocdn.com/s3/m/d0452c206d85ec3a87c24028915f804d2b1687f3.png)
STC51单片机普通IO口模拟IIC(I2C)接口通讯的程序代码STC 51单片机普通IO口模拟IIC(I2C)接口通讯的程序代码原文:(改自周立功软件包)#include <reg51.h>#include <intrins.h>#define uchar unsigned char /*宏定义*/#define uint unsigned intextern void Delay1us(unsigned char );sbit SDA=P1^6; /*模拟I2C数据传送位*/sbit SCL=P1^7; /*模拟I2C时钟控制位*/bit ack; /*应答标志位*//************************************************************** *****起动总线函数函数原型: void Start_I2c();功能: 启动I2C总线,即发送I2C起始条件.*************************************************************** *****/void Start_I2c(){SDA=1; /*发送起始条件的数据信号*/Delay1us(1);SCL=1;Delay1us(5); /*起始条件建立时间大于4.7us,延时*/SDA=0; /*发送起始信号*/Delay1us(5); /* 起始条件锁定时间大于4μs*/SCL=0; /*钳住I2C总线,准备发送或接收数据 */Delay1us(2);}/************************************************************** *****结束总线函数函数原型: void Stop_I2c();功能: 结束I2C总线,即发送I2C结束条件.*************************************************************** *****/void Stop_I2c(){SDA=0; /*发送结束条件的数据信号*/Delay1us(1); /*发送结束条件的时钟信号*/SCL=1; /*结束条件建立时间大于4us*/Delay1us(5);SDA=1; /*发送I2C总线结束信号*/Delay1us(4);}/*******************************************************************字节数据发送函数函数原型: void SendByte(uchar c);功能: 将数据c发送出去,可以是地址,也可以是数据,发完后等待应答,并对此状态位进行操作.(不应答或非应答都使ack=0)发送数据正常,ack=1; ack=0表示被控器无应答或损坏。
8051单片机与电脑的串口接收发送程序
![8051单片机与电脑的串口接收发送程序](https://img.taocdn.com/s3/m/96c607f8c8d376eeaeaa31fc.png)
{
EA = 0;
if(RI == 1) //当硬件接收到一个数据时,RI会置位
{
LED_Buffer[com_dat] = SBUF; //把从串口读出的数存到数组
RI = 0;
com_dat++;
E = 0;
delay();
E = 1;
delay();
}
/********************************************************************
* 名称 : write(uchar del)
* 功能 : 1602写数据函数
L1602_string(1,5,"ab cd ef;")
* 输入 : 行,列,需要输入1602的数据
* 输出 : 无
***********************************************************************/
void L1602_string(uchar hang,uchar lie,uchar *p)
}
/********************************************************************
* 名称 : Com_Int()
* 功能 : 串口中断子函数
* 输入 : 无
* 输出 : 无
***********************************************************************/
模拟串口的三种方法及C语言
![模拟串口的三种方法及C语言](https://img.taocdn.com/s3/m/766f25fcf021dd36a32d7375a417866fb84ac0de.png)
模拟串口的三种方法及C语言模拟串口是软件中模拟实现串口通信的一种方法,它是在电脑上通过软件模拟两个串口之间的传输,用来测试、调试串口相关的应用程序。
本文将介绍三种常见的模拟串口的方法,并提供C语言代码示例。
1.使用虚拟串口软件虚拟串口软件是一种用于模拟串口通信的应用程序。
它创建了虚拟的串口设备,使其在电脑上模拟出真实的串口通信环境。
通过虚拟串口软件,可以实现串口的模拟收发数据,可以连接到串口测试工具、串口调试工具或者自己编写的串口通信程序上。
以下是一个使用虚拟串口软件模拟串口通信的C语言代码示例:```c#include <stdio.h>#include <windows.h>int mai//打开虚拟串口//检测串口是否成功打开printf("Error in opening serial port\n");return 1;}//进行串口通信操作,如发送、接收数据//关闭串口return 0;```在这个示例中,我们使用了Windows操作系统的函数`CreateFile`来打开一个虚拟串口,这里的串口名称是"COM1"。
然后可以调用相关函数进行串口通信操作,最后用`CloseHandle`函数关闭串口。
2.使用串口驱动模拟在一些情况下,可以通过修改电脑的串口驱动程序来模拟串口通信。
这种方法需要更深入的了解操作系统的底层机制,并进行驱动程序的开发和修改。
通过修改串口驱动程序,可以模拟出一个虚拟的串口设备,通过这个设备进行串口通信。
以下是一个简单的C语言代码示例,用于修改串口驱动程序来模拟串口通信:```c#include <stdio.h>#include <fcntl.h>#include <unistd.h>int maiint fd;//打开串口设备fd = open("/dev/ttyS0", O_RDWR);//检测串口是否成功打开if (fd < 0)printf("Error in opening serial port\n");return 1;}//进行串口通信操作,如发送、接收数据//关闭串口设备close(fd);return 0;```在这个示例中,我们使用了Linux操作系统的函数`open`来打开一个串口设备,这里的设备名称是"/dev/ttyS0"。
51单片机模拟串口的三种方法
![51单片机模拟串口的三种方法](https://img.taocdn.com/s3/m/ed158c27915f804d2b16c1e2.png)
51单片机模拟串口的三种方法51单片机模拟串口的三种方法随着单片机的使用日益频繁,用其作前置机进行采集和通信也常见于各种应用,一般是利用前置机采集各种终端数据后进行处理、存储,再主动或被动上报给管理站。
这种情况下下,采集会需要一个串口,上报又需要另一个串口,这就要求单片机具有双串口的功能,但我们知道一般的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,刚好为一整数,如果为4800BP S则为96x2=192,如为19200BPS则为48,别的波特率就不算了,都刚好为整数个指令周期,妙吧。
至于别的晶振频率大家自已去算吧。
现在就以11.0592M的晶振为例,谈谈三种模拟串口的方法。
方法一:延时法通过上述计算大家知道,串口的每位需延时0.104秒,中间可执行96个指令周期。
#define uchar unsigned charsbit 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;uchar i=8;uchar temp=RDDYN;//发送8位数据位Delay2cp(RDDYN*1.5); //此处注意,等过起始位 while(i--){Output >>=1;if(RXD) Output |=0x80; //先收低位Delay2cp(35); //(96-26)/2,循环共占用26个指令周期}while(--temp) //在指定的时间内搜寻结束位。
单片机IO口模拟串口程序(发送+接收)
![单片机IO口模拟串口程序(发送+接收)](https://img.taocdn.com/s3/m/fa3698884028915f804dc253.png)
单片机IO口模拟串口程序(发送+接收)前一阵一直在做单片机的程序,由于串口不够,需要用IO口来模拟出一个串口。
经过若干曲折并参考了一些现有的资料,基本上完成了。
现在将完整的测试程序,以及其中一些需要总结的部分贴出来。
程序硬件平台:11.0592M晶振,STC单片机(兼容51)/************************************** ************************** 在单片机上模拟了一个串口,使用P2.1作为发送端* 把单片机中存放的数据通过P2.1作为串口TXD发送出去*************************************** ************************/#include <reg51.h>#include <stdio.h>#include <string.h>typedef unsigned char uchar;int i;uchar code info[] ={0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x5 5,0x55,0x55,0x55,0x55,0x55,0x55,0x55 };sbit newTXD = P2^1;//模拟串口的发送端设为P2.1void UartInit(){SCON = 0x50; // SCON: serail mode 1, 8-bit UARTTMOD |= 0x21; // T0工作在方式1,十六位定时PCON |= 0x80; // SMOD=1;TH0 = 0xFE; // 定时器0初始值,延时417us,目的是令模拟串口的波特率为2400bps fosc=11.0592MHzTL0 = 0x7F; // 定时器0初始值,延时417us,目的是令模拟串口的波特率为2400bps fosc=11.0592MHz// TH0 = 0xFD; // 定时器0初始值,延时417us,目的是令模拟串口的波特率为2400bps fosc=18.432MHz// TL0 = 0x7F; // 定时器0初始值,延时417us,目的是令模拟串口的波特率为2400bps fosc=18.432MHz}void WaitTF0(void){while(!TF0);TF0=0;TH0=0xFE; // 定时器重装初值fosc=11.0592MHzTL0=0x7F; // 定时器重装初值fosc=11.0592MHz// TH0 = 0xFD; // 定时器重装初值 fosc=18.432MHz// TL0 = 0x7F; // 定时器重装初值 fosc=18.432MHz}void WByte(uchar input){//发送启始位uchar j=8;TR0=1;newTXD=(bit)0;WaitTF0();//发送8位数据位while(j--){newTXD=(bit)(input&0x01); //先传低位WaitTF0();input=input>>1;}//发送校验位(无)//发送结束位newTXD=(bit)1;WaitTF0();TR0=0;}void Sendata(){for(i=0;i<sizeof(info);i++)//外层循环,遍历数组{WByte(info[i]);}}void main(){UartInit();while(1){Sendata();}}########################################## ####################################/************************************** ************************** 模拟接收程序,这个程序的作用从模拟串口接收数据,然后将这些数据发送到实际串口* 在单片机上模拟了一个串口,使用P3.2作为发送和接收端* 以P3.2模拟串口接收端,从模拟串口接收数据发至串口*************************************** ************************/#include<reg51.h>#include<stdio.h>#include<string.h>typedef unsigned char uchar ;//这里用来切换晶振频率,支持11.0592MHz 和18.432MHz//#define F18_432#define F11_0592uchar tmpbuf2[64]={0};//用来作为模拟串口接收数据的缓存struct{uchar recv :6 ;//tmpbuf2数组下标,用来将模拟串口接收到的数据存放到tmpbuf2中uchar send :6 ;//tmpbuf2数组下标,用来将tmpbuf2中的数据发送到串口}tmpbuf2_point={0,0};sbit newRXD=P3^2 ;//模拟串口的接收端设为P3.2void UartInit(){SCON=0x50 ;// SCON: serail mode 1, 8-bit UARTTMOD|=0x21 ;// TMOD: timer 1, mode 2, 8-bit reload,自动装载预置数(自动将TH1送到TL1);T0工作在方式1,十六位定时PCON|=0x80 ;// SMOD=1;#ifdef F11_0592TH1=0xE8 ;// Baud:2400 fosc=11.0592MHz 2400bps为从串口接收数据的速率TL1=0xE8 ;// 计数器初始值,fosc=11.0592MHz 因为TH1一直往TL1送,所以这个初值的意义不大TH0=0xFF ;// 定时器0初始值,延时208us,目的是令模拟串口的波特率为9600bps fosc=11.0592MHzTL0=0xA0 ;// 定时器0初始值,延时208us,目的是令模拟串口的波特率为9600bps fosc=11.0592MHz#endif#ifdef F18_432TH1=0xD8 ;// Baud:2400fosc=18.432MHz 2400bps为从串口接收数据的速率TL1=0xD8 ;// 计数器初始值,fosc=18.432MHz 因为TH1一直往TL1送,所以这个初值的意义不大TH0=0xFF ;// 定时器0初始值,延时104us,目的是令模拟串口的波特率为9600bps fosc=18.432MHzTL0=0x60 ;// 定时器0初始值,延时104us,目的是令模拟串口的波特率为9600bps fosc=18.432MHz#endifIE|=0x81 ;// 中断允许总控制位EA=1;使能外部中断0TF0=0 ;IT0=1 ;// 设置外部中断0为边沿触发方式TR1=1 ;// 启动TIMER1,用于产生波特率}void WaitTF0(void){while(!TF0);TF0=0 ;#ifdef F11_0592TH0=0xFF ;// 定时器重装初值模拟串口的波特率为9600bps fosc=11.0592MHz TL0=0xA0 ;// 定时器重装初值模拟串口的波特率为9600bps fosc=11.0592MHz #endif#ifdef F18_432TH0=0xFF ;// 定时器重装初值 fosc=18.432MHzTL0=0x60 ;// 定时器重装初值 fosc=18.432MHz#endif}//接收一个字符uchar RByte(){uchar Output=0 ;uchar i=8 ;TR0=1 ;//启动Timer0#ifdef F11_0592TH0=0xFF ;// 定时器重装初值模拟串口的波特率为9600bps fosc=11.0592MHz TL0=0xA0 ;// 定时器重装初值模拟串口的波特率为9600bps fosc=11.0592MHz #endif#ifdef F18_432TH0=0xFF ;// 定时器重装初值fosc=18.432MHzTL0=0x60 ;// 定时器重装初值fosc=18.432MHz#endifTF0=0 ;WaitTF0();//等过起始位//接收8位数据位while(i--){Output>>=1 ;if(newRXD)Output|=0x80 ;//先收低位WaitTF0();//位间延时}TR0=0 ;//停止Timer0return Output ;}//向COM1发送一个字符void SendChar(uchar byteToSend){SBUF=byteToSend ;while(!TI);TI=0 ;}void main(){UartInit();while(1){if(tmpbuf2_point.recv!=tmpbuf2_point.send)//差值表示模拟串口接收数据缓存中还有多少个字节的数据未被处理(发送至串口){SendChar(tmpbuf2[tmpbuf2_point.send++]);}}}//外部中断0,说明模拟串口的起始位到来了void Simulated_Serial_Start()interrupt 0{EX0=0 ;//屏蔽外部中断0tmpbuf2[tmpbuf2_point.recv++]=RByte(); //从模拟串口读取数据,存放到tmpbuf2数组中IE0=0 ;//防止外部中断响应2次,防止外部中断函数执行2次EX0=1 ;//打开外部中断0}~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~以上是两个独立的测试程序,分别是模拟串口发送的测试程序和接收的测试程序上面两个程序在编写过程中参考了这篇文章《51单片机模拟串口的三种方法》(在后文中简称《51》),但在它的基础上做了一些补充,下面是若干总结的内容:1、《51》在接收数据的程序中,采用的是循环等待的方法来检测起始位(见《51》的“附:51 IO 口模拟串口通讯C源程序(定时器计数法)”部分),这种方法在较大程序中,可能会错过起始位(比如起始位到来的时候程序正好在干别的,而没有处于判断起始位到来的状态),或者一直在检测起始位,而没有办法完成其他工作。
单片机串口收发时序
![单片机串口收发时序](https://img.taocdn.com/s3/m/760af0ebba4cf7ec4afe04a1b0717fd5360cb238.png)
单片机串口收发时序单片机串口收发时序是指单片机通过串口与外部设备进行数据的传输过程中所需要遵循的时序规则。
串口是指串行通信口,是一种适合低速、近距离通信的通信方式,串口通信的特点是信号的发送和接受是按位顺序进行的,这种通信方式的传输速率较慢,但是可以用于短距离的数据传输。
单片机串口收发过程可以分为发送和接收两个部分。
在发送数据的过程中,单片机需要按照一定的格式将数据转化为串行信号。
首先,单片机向发送端口写入一个起始位,通常是高电平的信号;然后,按照指定的数据格式,将各位数据依次发送出去,最后再发送一个停止位,通常是低电平的信号。
在接收数据的过程中,单片机需要按照时序规则来读取从外部设备传输过来的串行信号。
首先,单片机检测到一个电平变化,表示起始位的到来,然后按照指定数据格式读取数据位并进行解码,最后读取停止位来确定数据接收完成。
为了保证单片机串口收发过程的稳定和可靠,需要遵循以下的时序规则:1.起始位:单片机应该在信号的起始处接受到高电平的起始位。
2.数据位:单片机需要在接受到起始位后按照指定格式读取数据位,最常见的方式是LSB先发,一般是8位或9位。
3.校验位:为了减少数据传输过程中的错误,通常在数据位之后加上一个校验位。
常见的校验方式有奇偶校验和校验和两种,单片机需要按照指定规则计算出校验位,然后再发送出去。
4.停止位:单片机在发送数据完成后需要发送一个停止位来表示数据传输的结束。
通常是一个低电平的信号。
综上所述,单片机串口收发时序包括起始位、数据位、校验位和停止位。
遵循规定的时序规则可以使单片机与外部设备之间的通信更加稳定和可靠,从而有效提高通信效率。
单片机虚拟串口的使用方法
![单片机虚拟串口的使用方法](https://img.taocdn.com/s3/m/57c24c1dec630b1c59eef8c75fbfc77da269970b.png)
单片机虚拟串口的使用方法单片机的虚拟串口是一种非常常见的通信方式,它利用串口模拟的方式来进行数据的传输。
虚拟串口能够让单片机和计算机之间实现数据的传输和通讯,从而方便了开发者的开发工作,更好地实现了单片机与计算机的互联互通。
虚拟串口的使用方法如下:1. 确定虚拟串口的通信参数在使用虚拟串口前,首先要确认好虚拟串口的通信参数。
一般来说,包括波特率、数据位、停止位、奇偶校验等参数。
这些参数需要与单片机的串口通信参数相对应,否则通信将会失败。
2. 安装虚拟串口驱动程序在计算机上进行单片机项目的开发时,需要先安装对应的虚拟串口驱动程序。
常用的虚拟串口驱动程序有VirtualSerialDriver、FTDI等。
在安装驱动程序时,需要根据计算机的操作系统版本,选择对应的驱动程序版本。
3. 编写单片机程序在单片机中涉及到虚拟串口的程序中,需要先初始化串口通信参数,并打开串口,然后循环等待从串口接收到的数据。
在循环中,可以使用串口发送数据给计算机,或者从计算机接收数据。
4. 在计算机上打开虚拟串口设备在单片机程序中设置好虚拟串口的通信参数后,需要在计算机上打开虚拟串口设备。
在计算机的设备管理器中,能够看到已经成功安装的虚拟串口设备。
打开对应的串口,设置对应的通信参数即可。
5. 测试通信在单片机和计算机之间建立虚拟串口连接后,需要进行测试,确保串口通信正常。
可以先从单片机发送数据给计算机,观察是否能够在计算机上接收到数据;然后,可以在计算机上发送数据给单片机,观察单片机是否能够接收到数据。
如果测试结果正确,就可以通过这个虚拟串口通讯了。
总的来说,单片机虚拟串口的使用是比较简单的,只需设置好通信参数,安装对应的驱动程序,然后编写好单片机程序,最后进行测试即可。
虚拟串口通信的优点是方便快捷,能够更好地连接单片机与计算机,方便数据传输和控制。
因此,在实际应用中,虚拟串口通信被广泛应用于各种单片机项目开发中。
单片机串口通信的发送与接收
![单片机串口通信的发送与接收](https://img.taocdn.com/s3/m/a2b1a7064531b90d6c85ec3a87c24028915f8593.png)
51单片机的串口,是个全双工的串口,发送数据的同时,还可以接收数据。
当串行发送完毕后,将在标志位TI 置1,同样,当收到了数据后,也会在RI 置1。
无论RI 或TI 出现了1,只要串口中断处于开放状态,单片机都会进入串口中断处理程序。
在中断程序中,要区分出来究竟是发送引起的中断,还是接收引起的中断,然后分别进行处理。
看到过一些书籍和文章,在串口收、发数据的处理方法上,很多人都有不妥之处。
接收数据时,基本上都是使用“中断方式”,这是正确合理的。
即:每当收到一个新数据,就在中断函数中,把RI 清零,并用一个变量,通知主函数,收到了新数据。
发送数据时,很多的程序都是使用的“查询方式”,就是执行while(TI ==0); 这样的语句来等待发送完毕。
这时,处理不好的话,就可能带来问题。
看了一些网友编写的程序,发现有如下几条容易出错:1.有人在发送数据之前,先关闭了串口中断!等待发送完毕后,再打开串口中断。
这样,在发送数据的等待期间内,如果收到了数据,将不能进入中断函数,也就不会保存的这个新收到的数据。
这种处理方法,就会遗漏收到的数据。
2.有人在发送数据之前,并没有关闭串口中断,当TI = 1 时,是可以进入中断程序的。
但是,却在中断函数中,将TI 清零!这样,在主函数中的while(TI ==0);,将永远等不到发送结束的标志。
3.还有人在中断程序中,并没有区分中断的来源,反而让发送引起的中断,执行了接收中断的程序。
对此,做而论道发表自己常用的方法:接收数据时,使用“中断方式”,清除RI 后,用一个变量通知主函数,收到新数据。
发送数据时,也用“中断方式”,清除TI 后,用另一个变量通知主函数,数据发送完毕。
这样一来,收、发两者基本一致,编写程序也很规范、易懂。
更重要的是,主函数中,不用在那儿死等发送完毕,可以有更多的时间查看其它的标志。
实例:求一个PC与单片机串口通信的程序,要求如下:1、如果在电脑上发送以$开始的字符串,则将整个字符串原样返回(字符串长度不是固定的)。
gpio 模拟串口通讯的波特率
![gpio 模拟串口通讯的波特率](https://img.taocdn.com/s3/m/75c3cf5f876fb84ae45c3b3567ec102de2bddfaf.png)
gpio 模拟串口通讯的波特率
GPIO模拟串口通讯的波特率取决于所使用的硬件和软件设置。
一般来说,如果你使用的是单片机或者嵌入式系统,你需要通过GPIO来模拟串口通讯,这种情况下,波特率是由时钟频率和串口通
讯协议决定的。
首先,你需要确定你的系统时钟频率,然后根据串口通讯协议(如UART)的要求来选择合适的波特率。
常见的波特率包括9600、19200、38400、115200等,当然也可以选择其他非标准波特率。
在
使用GPIO模拟串口通讯时,你需要通过编程来确保GPIO的输入输
出频率符合所选波特率的要求。
在软件层面,你需要编写相应的驱动程序或者使用现有的GPIO
库来配置GPIO引脚,设置输入输出频率,并实现数据的发送和接收。
此外,在使用GPIO模拟串口通讯时,你还需要考虑到时序的稳定性
和数据的可靠性,因为GPIO模拟串口通讯相比硬件串口会更容易受
到外部干扰和时序偏差的影响。
总之,GPIO模拟串口通讯的波特率取决于硬件的时钟频率和串
口通讯协议的要求,同时也需要在软件层面进行相应的配置和编程来实现所需的波特率。
希望这个回答能够全面解答你的问题。
(完整版)单片机串口接收发送并显示字符串
![(完整版)单片机串口接收发送并显示字符串](https://img.taocdn.com/s3/m/3da16abe0c22590103029d1a.png)
#include <reg52.h>#define uchar unsigned char#define uint unsigned intsbit rs=P2^5; //命令/数据选择sbit rw=P2^4; //读写口sbit e=P2^3; //锁存控制uchar data table[32]; //暂存数组,可以将10改为你需要的数值/***********************************************串行口初始化波特率9600,定时器1,工作方式2*************************************************/void serial_init(void){TMOD=0x20;//计时器1作为比特率发生器,方式2TH1=0xfd;TL1=0xfd; //装入初值TR1=1;//计时中断允许SM0=0;SM1=1;//串行口工作于方式2ES=1;//串行口中断允许REN=1;//接收允许EA=1;// 总中断允许}/********************* **************************串行口传送数据传送显示数组各字符给计算机*************************************************/void send(uchar *dis){while(*dis!='\0'){SBUF=*dis;dis++;while(!TI);TI=0; //软件请发送中断}}//*************************************************************************************** ***********//延时函数//*************************************************************************************** ***********void delay(uint time) //int型数据为16位,所以最大值为65535{uint i,j; //定义变量i,j,用于循环语句for(i=0;i<time;i++) //for循环,循环50*time次for(j=0;j<100;j++); //for循环,循环50次}//*************************************************************************************** ***********//向LCD写一命令//*************************************************************************************** ***********void wcode(uchar t){rs=0; // 写的是命令rw=0; // 写状态e=1; //使能P0=t; //写入命令delay(20); //等待写入,如果时间太短,会导致液晶无法显示e=0; //数据的锁定}//*************************************************************************************** ***********//向LCD写一数据//*************************************************************************************** ***********void wdata(uchar t){rs=1; // 写的是数据rw=0; // 写状态e=1; //使能P0=t; //写入数据delay(20); //等待写入,如果时间太短,会导致液晶无法显示e=0; //数据的锁定}//*************************************************************************************** ***********//LCD显示第一行//**************************************************************************************************void xian1(){uchar i;wcode(0x80); //设置第一行显示地址for(i=0;i<16;i++) //循环16次,写完1行{wdata(table[i]); //写入该行数据}}//*************************************************************************************** ***********//LCD显示第二行//*************************************************************************************** ***********void xian2(){uchar i;wcode(0xc0); //设置第二行显示地址for(i=16;i<33;i++) //循环16次,写完1行{wdata(table[i]); //写入该行数据}}//*************************************************************************************** ***********//LCD 初始化//*************************************************************************************** ***********void InitLCD(){wcode(0x01); //清屏wcode(0x06); //输入方式控制,增量光标不移位wcode(0x0e); //显示开关控制wcode(0x38); //功能设定:设置16x2显示,5x7显示,8位数据接口}//*************************************************************************************** ***********//主函数//*************************************************************************************** ***********void main(){。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
*把单片机中存放的数据通过P2.1作为串口TXD发送出去
***************************************************************/
#in elude<reg51.h>
#i nclude<stdio.h>
/***************************************************************
*模拟接收程序,这个程序的作用从模拟串口接收数据,然后将这些数据发送到实际 串口
*在单片机上模拟了一个串口,使用P3.2作为发送和接收端
*以P3.2模拟串口接收端,从模拟串口接收数据发至串口
THO=OxFF;//定时器0初始值,延时208us,目的是令模拟串口的波特率为9600bps
fosc=11.0592MHz
送到TL1);T0工作在方式1,十六位定时
PCON|=0x80;//SMOD=1;
#ifdef F11_0592
TH1=0xE8 ; // Baud:2400fosc=11.0592MHz 2400bps为从串口接收数据的速率
TL1=0xE8;//计数器初始值,fosc=11.0592MHz因为TH1一直往TL1送,所以这个初值的意义不大
{
WByte(i nfo[i]);
}
}
void main()
{
UartI nit();
while (1)
{
Se ndata();
}
}
II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II
// SCON: serail mode 1,8-bit UART
// T0工作在方式1,十六位定时
//SMOD=1;
0xFE;II定时器0初始值,延时417us,目的是令模拟串口的波特率为
2400bps fosc=11.0592MHz
TL0=0x7F;II
2400bps fosc=11.0592MHz
IITH0=0xFD;II定时器0初始值,延时417us,目的是令模拟串口的波特率
为2400bps fosc=18.432MHz
IITL0=0x7F;II定时器0初始值,延时417us,目的是令模拟串口的波特率为
2400bps fosc=18.432MHz
}
void WaitTF0( void )
{
}tmpbuf2_poi nt={0,0};
sbit newRXD=P3A2 ; //模拟串口的接收端设为P3.2
void Uartl nit()
{
SCON=0x50 ; // SCON: serail mode 1, 8-bit UART
TMOD|=0x21 ; // TMOD: timer 1, mode 2, 8-bit reload,自动装载预置数(自动将TH1
//#defi ne F18_432
#defi neF11_0592
uchar tmpbuf2[64]={0};
//用来作为模拟串口接收数据的缓存
struct
{
uchar recv :6 ;//tmpbuf2数组下标,用来将模拟串口接收到的数据存放到tmpbuf2中
uchar send:6;//tmpbuf2数组下标,用来将tmpbuf2中的数据发送到串口
while (!TFO);
TFO=O;
THO=OxFE;//定时器重装初值fosc=11.0592MHz
TL0=0x7F;//定时器重装初值fosc=11.0592MHz
void WByte(uchar in put)
{
//发送启始位
uchar j=8;
TR0=1;
newTXD=(bit)O;
WaitTF0();
#in clude<stri ng.h>
typedef unsigned char uchar;
int i;
uchar code in fo[]=
{
0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x5
5
};
//发送8位数据位
while (j--)
{
newTXD=(bit)(i nput&0x01);
WaitTF0();
in put= in put>>1;
}
//发送校验位(无)
//发送结束位
n ewTXD=(bit)1;
WaitTF0();
TR0=0;
}
void Sendata()
{
for (i=0;i<sizeof(info);i++)
前一阵一直在做单片机的程序,由于串口不够,需要用10口来模拟出一个串口。 经过若干曲
折并参考了一些现有的资料,基本上完成了。现在将完整的测试程序,以及其中一些需要总 结的部分贴出来。
程序硬件平台:11.0592M晶振,STC单片机(兼容51)
/**************************************************************
a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a
***************************************************************/
#in elude<reg51.h>
#i nclude<stdio.h>
#in clude<stri ng.h>
typedefunsigned char uchar ;
//这里用来切换晶振频率,支持11.0592MHz和18.432MHz