利用串口与并口实现51内核单片机的在线编程
51单片机的串口通信程序(C语言)
51单片机的串口通信程序(C语言) 51单片机的串口通信程序(C语言)在嵌入式系统中,串口通信是一种常见的数据传输方式,也是单片机与外部设备进行通信的重要手段之一。
本文将介绍使用C语言编写51单片机的串口通信程序。
1. 硬件准备在开始编写串口通信程序之前,需要准备好相应的硬件设备。
首先,我们需要一块51单片机开发板,内置了串口通信功能。
另外,我们还需要连接一个与单片机通信的外部设备,例如计算机或其他单片机。
2. 引入头文件在C语言中,我们需要引入相应的头文件来使用串口通信相关的函数。
在51单片机中,我们需要引入reg51.h头文件,以便使用单片机的寄存器操作相关函数。
同时,我们还需要引入头文件来定义串口通信的相关寄存器。
3. 配置串口参数在使用串口通信之前,我们需要配置串口的参数,例如波特率、数据位、停止位等。
这些参数的配置需要根据实际需要进行调整。
在51单片机中,我们可以通过写入相应的寄存器来配置串口参数。
4. 初始化串口在配置完串口参数之后,我们需要初始化串口,以便开始进行数据的发送和接收。
初始化串口的过程包括打开串口、设置中断等。
5. 数据发送在串口通信中,数据的发送通常分为两种方式:阻塞发送和非阻塞发送。
阻塞发送是指程序在发送完数据之后才会继续执行下面的代码,而非阻塞发送是指程序在发送数据的同时可以继续执行其他代码。
6. 数据接收数据的接收与数据的发送类似,同样有阻塞接收和非阻塞接收两种方式。
在接收数据时,需要不断地检测是否有数据到达,并及时进行处理。
7. 中断处理在串口通信中,中断是一种常见的处理方式。
通过使用中断,可以及时地响应串口数据的到达或者发送完成等事件,提高程序的处理效率。
8. 串口通信实例下面是一个简单的串口通信实例,用于在51单片机与计算机之间进行数据的传输。
```c#include <reg51.h>#include <stdio.h>#define BAUDRATE 9600#define FOSC 11059200void UART_init(){TMOD = 0x20; // 设置定时器1为模式2SCON = 0x50; // 设置串口为模式1,允许接收TH1 = 256 - FOSC / 12 / 32 / BAUDRATE; // 计算波特率定时器重载值TR1 = 1; // 启动定时器1EA = 1; // 允许中断ES = 1; // 允许串口中断}void UART_send_byte(unsigned char byte){SBUF = byte;while (!TI); // 等待发送完成TI = 0; // 清除发送完成标志位}unsigned char UART_receive_byte(){while (!RI); // 等待接收完成RI = 0; // 清除接收完成标志位return SBUF;}void UART_send_string(char *s){while (*s){UART_send_byte(*s);s++;}}void main(){UART_init();UART_send_string("Hello, World!"); while (1){unsigned char data = UART_receive_byte();// 对接收到的数据进行处理}}```总结:通过以上步骤,我们可以编写出简单的51单片机串口通信程序。
51单片机 12864液晶显示并口和串口连接程序
sent((DATA&0X0F)<<4); //低位
}
void AUTO(uchar *add)
{
uchar cnt=0;
while(*(add+cnt)!='\0')
{
writLCD(1,*(add+cnt));
cnt++;
}
}
void wirtthings(uchar lines,uchar *add)//writ data to which line
else
RW=0;
delay(10);
SCK=1;
DATA=DATA<<1;
}
}
void writLCD(bit flag,uchar DATA) //writ COM or data in address
{
if(flag)
sent(0xfa);//1写数据
else
sent(0xf8);//0写指令
//writLCD(0,0x01);
wirtthings(4,"什么,only You!");
//writLCD(0,0x01);
wirtthings(1,"联系方式:");
//writLCD(0,0x01);
wirtthings(2,"QQ:452658536");
delay(100);
writLCD(0,0x01);
}
}
void delay(uchar i)
{
uchar j;
while(i--)
51单片机串口设置及应用
51单片机串口设置及应用单片机的串口设置及应用是指通过单片机的串口功能来进行通信的一种方式。
串口通信是一种全双工通信方式,可以实现双向数据传输。
单片机通过串口可以与其他设备进行通信,如计算机、传感器、LCD显示屏等。
1. 串口设置:单片机的串口通信一般需要进行以下设置:(1)串口模式选择:要根据实际情况选择串口工作模式,一般有异步串口和同步串口两种。
(2)波特率设置:串口通信需要设置一个波特率,即数据传输速率。
常见的波特率有9600、19200、115200等,需要与通信的设备保持一致。
(3)数据位设置:设置传输的数据位数,常见的有8位、9位等。
(4)停止位设置:设置停止位的个数,常见的有1位、2位等。
(5)校验位设置:可以选择是否启用校验位,校验位主要用于检测数据传输的正确性。
2. 串口应用:串口通信在很多领域都得到广泛应用,下面列举几个常见的应用场景:(1)串口与计算机通信:通过串口可以实现单片机与计算机的通信,可以进行数据的读写、控制等操作。
例如,可以通过串口将传感器采集到的数据发送给计算机,由计算机进行进一步处理分析。
(2)串口与传感器通信:串口可以与各种传感器进行通信,可以读取传感器采集到的数据,并进行处理和控制。
例如,可以通过串口连接温度传感器,读取实时的温度数据,然后进行温度控制。
(3)串口与LCD显示屏通信:通过串口可以实现单片机与LCD显示屏的通信,可以将需要显示的数据发送给LCD显示屏进行显示。
例如,可以通过串口将单片机采集到的数据以数字或字符的形式显示在LCD上。
(4)串口与外部存储器通信:通过串口可以与外部存储器进行通信,可以读写存储器中的数据。
例如,可以通过串口读取SD卡中存储的图像数据,然后进行图像处理或显示。
(5)串口与其他设备通信:通过串口可以和各种其他设备进行通信,实现数据的传输和控制。
例如,可以通过串口与打印机通信,将需要打印的数据发送给打印机进行打印。
总结:单片机的串口设置及应用是一种实现通信的重要方式。
51单片机与串口通信代码
51单片机与串口通信代码作者:佚名来源:本站原创点击数: 9407 更新时间:2007年06月17日【字体:大中小】1. 发送:向总线上发命令2. 接收:从总线接收命令,并分析是地址还是数据。
3. 定时发送:从内存中取数并向主机发送.经过调试,以上功能基本实现,目前可以通过上位机对单片机进行实时控制。
程序如下://这是一个单片机C51串口接收(中断)和发送例程,可以用来测试51单片机的中断接收//和查询发送,另外我觉得发送没有必要用中断,因为程序的开销是一样的#i nclude <reg51.h>#i nclude<stdio.h>#i nclude <string.h>#define INBUF_LEN 4 //数据长度unsigned char inbuf1[INBUF_LEN];unsigned char checksum,count3 , flag,temp,ch;bit read_flag=0;sbit cp=P1^1;sbit DIR=P1^2;int i;unsigned int xdata *RAMDATA; /*定义RAM地址指针*/unsigned char a[6] ={0x11,0x22,0x33,0x44,0x55,0x66} ;void init_serialcomm(void){SCON=0x50; //在11.0592MHz下,设置串行口波特率为9600,方式1,并允许接收 PCON=0x00;ES=1;TMOD=0x21; //定时器工作于方式2,自动装载方式TH0=(65536-1000)%256;TL0=(65536-1000)/256;TL1=0xfd;TH1=0xfd;ET0=1;TR0=1;TR1=1;// TI=0;EA=1;// TI=1;RAMDATA=0x1F45;}void serial () interrupt 4 using 3{if(RI){ RI=0;ch=SBUF;TI=1; //置SBUF空switch(ch){case 0x01 :printf("A"); TI=0;break;case 0x02 :printf("B"); TI=0;break;case 0x03 :printf("C"); TI=0;break;case 0x04 :printf("D"); TI=0;break;default :printf("fg"); TI=0;break;}}}//向串口发送一个字符void timer0() interrupt 1 using 3{// char i;flag++;TH0=0x00;TL0=0x00;if(flag==10){// cp=!cp;// for(i=0;i<6;i++)P2=0x25;TI=1;temp=*RAMDATA;printf("%c",temp);TI=0;// RAMDATA--;flag=0;}}//主程序main(){init_serialcomm(); //初始化串口//向6264中送数据{*RAMDATA=0x33;}while(1){*RAMDATA=0x33;;}}调试过程中遇到的问题:1. 发送过程:在发送时必须保证TI=1:即发送缓冲器为空,否则将导致数据发不出去,如果想强制发送可以用:T I=1.具体发送数据:利用printf(“akjdfaklfj”);函数直接发送即可。
51单片机双机串行通信设计
51单片机双机串行通信设计51单片机是一款广泛应用于嵌入式系统中的微控制器,具有高性能和低功耗的特点。
在一些场景中,需要使用51单片机之间进行双机串行通信,以实现数据传输和协同工作。
本文将介绍51单片机双机串行通信的设计,包括硬件连接和软件编程。
一、硬件连接1.串行通信口选择:51单片机具有多个串行通信口,如UART、SPI 和I2C等。
在双机串行通信中,可以选择其中一个串行通信口作为数据传输的接口。
一般来说,UART是最常用的串行通信口之一,因为它的硬件接口简单且易于使用。
2.引脚连接:选定UART口作为串行通信口后,需要将两个单片机之间的TX(发送)和RX(接收)引脚相连。
具体的引脚连接方式取决于所使用的单片机和外设,但一般原则上是将两个单片机的TX和RX引脚交叉连接。
二、软件编程1.串行通信初始化:首先需要通过软件编程来初始化串行通信口。
在51单片机中,可以通过设置相应的寄存器来配置波特率和其他参数。
具体的初始化代码可以使用C语言编写,并根据所使用的开发工具进行相应的配置。
2.发送数据:发送数据时,可以通过写入相应的寄存器来传输数据。
在51单片机中,通过将数据写入UART的发送寄存器,即可将数据发送出去。
发送数据的代码通常包括以下几个步骤:(1)设置发送寄存器;(2)等待数据发送完成;(3)清除数据发送完成标志位。
3.接收数据:接收数据时,需要通过读取相应的寄存器来获取接收到的数据。
在51单片机中,可以通过读取UART的接收寄存器,即可获取到接收到的数据。
接收数据的代码通常包括以下几个步骤:(1)等待数据接收完成;(2)读取接收寄存器中的数据;(3)清除数据接收完成标志位。
4.数据处理:接收到数据后,可以进行相应的数据处理。
根据具体的应用场景,可以对接收到的数据进行解析、计算或其他操作。
数据处理的代码可以根据具体的需求进行编写。
5.中断服务程序:在双机串行通信中,使用中断可以提高通信的效率。
51单片机串口通信(相关例程)
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单片机串口通信的基础知识和相关编程例程,包括串口发送数据、串口接收数据和串口发送字符串。
Linux下 QT串口与51单片机通信实例
QT串口与51单片机通信通过这个小例子主要想说明QT怎样进行线程编程的思想,实例如图,好吧,下面是过程上一个例子我们采用的是手工编写代码的方法,这个例子我们来玩一下designer,其实Qt4己经把界面与功能分开了,用designer来进行界面设计,再手工编写一些功能,如信号与槽,这样开发效率会大大提高,呵呵,开一个终端,输入/usr/local/Trolltech/Qt-4.5.1/bin/designer,如果第一次打开出现字体不对,可以打开qtconfig进行一些相关配置,打开后我们新建一个Main Window,在右边的属性框中设置一下界面大小,1.我ARM板的LCD大小为320x240,所以我也设为320x240;2.左边是一些我们常用的窗口部件,这里我们用到一个lable标签来做显示,再放几个pushButton按钮,在属性objectName重新更改它的名字,改为我们记得的,这样在写功能时记得哪个按钮叫什么名字,对于一个初学QT的人来说,很想知道每一个部件到底有什么信号和槽,别急,我们可以这样来看,选中一个lable,按F4,再点击lable拖动出现接地符号时松开,弹出编辑信号与槽,这时左边列出的是信号,右边为槽,这里我们不用配置连接,等下我们再手工写,3最后我们用到一个lable标签和三个pushButton按钮,并命名为dis_label、writeButton、readButton、closeButton,然后保存为mainwindow.ui,这样designer就完工了,呵呵..4.下面我们编写一个线程,用于管理串口收发工作,它不涉及到任何界面,只做好它的本份工作就得了,编写一个thread.h文件gedit thread.h,#ifndef THREAD_H#define THREAD_H#include<QThread>class Thread:public QThread{Q_OBJECTpublic:Thread();char buf[128];volatile bool stopped;volatile bool write_rs;volatile bool read_rs;protected:virtual void run();};#endif我们定义一个Thread类,它继承于QThread,看到只设有一些变量和一个run函数,virtual表示为虚函数,你也可以去掉,加上去会增加一些内存开销,但提高了效率,对于这个小程序是看不出什么效果的,volatile这个大家都懂了吧,就是防止偷懒,呵呵,5.再看看thread.cpp#include"thread.h"#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <termios.h> //串口用到的#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <strings.h>#define BAUDRATE B9600//#define RS_DEVICE "/dev/ttyS0" //串口1#define RS_DEVICE "/dev/ttySAC1" //串口1Thread::Thread(){} //析构void Thread::run() //这就是线程的具体工作了int fd,c=0,res;struct termios oldtio,newtio; //termios结构是用来保存波特率、字符大小等printf("start...\n");fd=open(RS_DEVICE,O_RDWR|O_NOCTTY); //以读写方式打开串口。
51单片机串口多机通信的实现和编程
51 单片机串口多机通信的实现和编程
一、51 单片机的主从模式,首先要设定工作方式3:(主从模式+波特率可变)
SCON 串口功能寄存器:SM0=1;SM1=1(工作方式3)
注:主机和从机都要为工作方式3。
【工作方式2 (SM0 SM1 :1 0):串行口为11 位异步通信接口。
发送或接收
一帧信息包括1 位起始位0、8 位数据位、1 位可编程位、1 位停止位1。
发
送数据:发送前,先根据通信协议由软件设置TB8 为奇偶校验位或数据标识位,然后将要发送的数据写入SBUF,即能启动发送器。
发送过程是由执行任何一条以SBUF 为目的寄存器的指令而启动的,把8 位数据装入SBUF,
同时还把TB8 装到发送移位寄存器的第9 位上,然后从TXD(P3.1)端口输出
一帧数据。
接收数据:先置REN=1,使串行口为允许接收状态,同时还要将RI 清0。
然后再根据SM2 的状态和所接收到的RB8 的状态决定此串行口在
信息到来后是否置R1=1,并申请中断,通知CPU 接收数据。
当SM2=0 时,
不管RB8 为0 还是为1,都置RI=1,此串行口将接收发送来的信息。
当
SM2=1 时,且RB8=1,表示在多机通信情况下,接收的信息为地址帧, 此时
置RI=1,串行口将接收发来的地址。
当SM2=1 时,且RB8=0,表示在多机通
信情况下,接收的信息为数据帧, 但不是发给本从机的,此时RI 不置为1,。
51单片机串口通信程序
51单片机串口通信程序51单片机是我国自主研发的一款微控制器,在国内广泛应用于各种电子设备中。
在很多应用场景中,需要通过串口进行通信,以实现数据传输。
本文将介绍51单片机串口通信程序的编写方法。
一、串口介绍串口是一种通信接口,用于在电子设备之间传输数据。
其主要特点是一条通信线路同时只能传输一位数据,因此称为串口。
串口和并口属于不同的通信接口标准。
串口的优点是具有通信距离远、传输速率快、可靠性高等优点,因此广泛应用于各种场合中。
串口有两种工作模式:同步模式和异步模式。
在实际应用中,异步串口通信更为常见。
二、异步串口通信原理在异步串口通信中,数据的传输是通过发送端和接收端的时钟信号不同步实现的。
在发送数据时,发送端会发出一个起始位,接下来是数据位,最后是一个或多个停止位。
在接收端,当检测到起始位时,开始接收数据。
根据通信协议,在接收完数据位后,接收端会判断是否正确,然后再结束本次通信。
1. 硬件连接在51单片机和电脑之间进行串口通信,需要用到串口转USB线。
将串口转USB线的TxD接口与51单片机的P3.1接口相连,RxD接口与P3.0接口相连。
此外,需要一个5V的电源供给51单片机。
2. 准备工作在编写程序之前,需要进行一些准备工作:(1)将P3口设为外部中断P3口的最低2位是外部中断的2个输入端,需要将它们设为中断输入。
EA=1;EX0=1;(2)设置波特率串口通信需要设置波特率。
常见的波特率有9600、19200、38400等。
对应的波特率常数为0xFD、0xFA、0xF4等。
TH1=0xFD;//波特率9600(3)使能串口中断在发送和接收数据时,会不断产生中断,需要将中断使能。
ES=1;//允许串口中断3. 编写程序(1)发送数据void SendData(unsigned char SendBuff[],unsigned int ULength){unsigned int i;for(i=0;i<ULength;i++){SBUF=SendBuff[i];//发送数据while(TI==0); //等待,直到发送完成TI=0;}}(2)接收数据(3)主函数TMOD|=0x20;//定时器1工作方式2TH1=0xFD;//波特率9600TR1=1;//打开定时器1SCON=0x50;//串口方式1,8位数据,无校验,1停止位EA=1;//开总中断ES=1;//开串口中断while(1){SendData(pSendData,4);//发送数据 RecvData(pRecvData,4);//接收数据if(pRecvData[0]=='K'){P0=0x01;//点亮LED}else{P0=0x00;//关闭LED}}}四、总结。
51系列单片机多串口通讯任务的实现
第31 卷第6 期2005 年12 月东华大学学报(自然科学版)J O U RN AL O F DON GHU A U N IV ERSI T YVol . 31 , No . 6Dec. 20055 1系列单片机多串口通讯任务的实现吴佳1,钱伟康2(1.上海理工大学中德学院,上海,200093 ;2.上海理工大学电气工程学院,上海,200093 )51系列单片机系统应用日益广泛的今天,又是单片机的主要通讯方式,然而传统51单片机的串口已很难满足当今高速、多串口通讯的应用要求,新的串口通讯方式就显得尤为重要了。
本文就如何利用51关键词:单片机,串口通讯,汇编语言中图分类号: TP 520在单片机系统的应用中,串口通讯是单片机的主要通讯方式,它的基本原理是通过对单片机输出T XD和R XD每隔一定时间输出高电平或低电平来实现数据的通讯。
因此单片机的串口受到定时器T1的影响,往往传送速度会受到很大限制,当波特率大于1 9 . 2 k时,传统串口就很难实现了(表1所示为常用串口通讯模式)。
此外现今的单片机系统不但要求要和下位机通讯,而且还要同时和上位机通讯(一般为P C机)。
由此可见,为了满足现今单片机系统的多级通讯要求,传统的单片机串口在功能和应用上已经显得捉襟见肘了,因此用软件来模拟串口通讯就有了很大的应用价值。
表1常用波特率与其他参数设置串口工作方式波特率/(bit・s - 1)晶振频率/MHz定时器T1SMOD模式定时器初值62. 5 k12120FFH19. 2 k11. 059 2120FDH9. 6 k11. 059 2020FDH方式1和方式34. 8 k11. 0592020FAH2. 4 k11. 059 2020F4H1. 2 k11. 059 2020E8H137. 5 k11. 059 2021DH…………………………1多串口通讯原理首先讨论串口通讯的工作原理(这里只讨论异步串行通讯)。
51单片机与串口通信代码
51单片机与串口通信代码在当今科技发展迅速的时代,嵌入式系统的应用越来越广泛。
而51单片机是一类常见的嵌入式控制器,它具有体积小巧、功耗低、价格便宜等特点,因此被广泛应用于各个领域。
而串口通信是实现单片机与计算机之间数据传输的常见方式,本文将介绍51单片机与串口通信的相关代码。
1. 串口通信概述串口通信是指通过串行接口,将数据一位一位地传输。
单片机通过串口与计算机或其他设备之间进行数据传输,实现信息的收发和控制指令的执行。
串口通信常用的协议包括RS232、RS485和UART等。
在51单片机中,一般选用UART协议。
2. 串口通信的硬件连接在使用51单片机与计算机进行串口通信时,需要进行相应的硬件连接。
首先,需要将单片机的串口引脚(一般是P3口)与计算机的串口(COM口)进行连接。
单片机的TXD引脚连接到计算机的RXD引脚,而单片机的RXD引脚连接到计算机的TXD引脚。
此外,还需要相连的地线进行电位的匹配。
3. 串口通信的软件设置在使用51单片机进行串口通信时,需要对单片机的串口进行相应的软件设置。
首先,需要设置波特率,波特率指每秒传送的位数,常见的波特率有9600、115200等。
通过设置相同的波特率,实现单片机与计算机之间的数据传输。
其次,还需要设置数据位、停止位和校验位等参数,以确保数据的正确传输。
4. 单片机发送数据的代码示例下面是一个简单的51单片机发送数据的代码示例:```c#include <reg51.h>void main() {TMOD = 0x20; // 配置定时器1为工作方式2TH1 = 0xFD; // 设置波特率为9600SCON = 0x50; // 允许串口工作TR1 = 1; // 启动定时器1while (1) {SBUF = 'A'; // 发送数据while (!TI); // 等待数据发送完毕TI = 0; // 清除发送标志位}}```5. 单片机接收数据的代码示例下面是一个简单的51单片机接收数据的代码示例:```c#include <reg51.h>void main() {TMOD = 0x20; // 配置定时器1为工作方式2TH1 = 0xFD; // 设置波特率为9600SCON = 0x50; // 允许串口工作TR1 = 1; // 启动定时器1while (1) {if (RI) { // 判断是否有数据接收P1 = SBUF; // 将接收到的数据存入P1口RI = 0; // 清除接收标志位}}}```6. 总结本文介绍了51单片机与串口通信代码的相关内容。
51单片机串口变并口汇编程序
51单片机串口变并口汇编程序一、背景介绍单片机是一种集成了处理器、存储器和输入输出接口的微型计算机系统,广泛应用于各种电子设备中。
其中,51单片机是一种非常常见且功能强大的单片机型号。
而串口和并口是单片机与外部设备进行数据传输的两种常见方式。
本文将探讨如何使用汇编语言编写一个将串口转换为并口的51单片机程序。
二、串口与并口的概念1. 串口串口是指利用一对数据线进行数据传输的通信接口。
串口通信可以实现双向数据传输,常用于计算机与外部设备之间的数据交换。
串口通信的优势在于能够以较低的成本实现较长距离的数据传输,且占用的引脚较少。
2. 并口并口是指利用多条数据线进行数据传输的通信接口。
并口通信一般只能实现单向数据传输,常用于单片机与外围设备之间的数据交换。
并口通信的优势在于能够以较高的速度进行数据传输,但由于占用的引脚较多,因此在设计中需要考虑引脚的分配和接口电路的设计。
三、串口变并口的原理串口与并口的数据传输方式和电气特性不同,因此需要一定的电路转换才能实现串口变并口。
常见的串口变并口电路采用的是移位寄存器,通过串行-并行转换实现数据的传输。
串口变并口的原理如下:1.串口接收到的数据通过串行-并行转换电路和移位寄存器转换为并行数据。
2.并口的数据通过并行-串行转换电路和移位寄存器转换为串行数据,然后通过串口发送出去。
四、51单片机串口变并口汇编程序实现步骤以下是使用51单片机汇编语言编写的串口变并口程序的实现步骤:1.初始化串口:设置串口的波特率、数据位数、停止位、校验位等参数。
2.初始化并口:设置并口的工作模式、数据线的方向等参数。
3.循环接收串口数据:使用串口中断,将接收到的串口数据存储到缓冲区中。
4.将串口数据转换为并口数据:通过移位寄存器和并口接口电路将串口数据转换为并口数据。
5.将并口数据发送出去:将转换后的并口数据通过并口接口电路发送给外部设备。
6.跳转回循环接收串口数据的步骤,完成循环。
51单片机串口通信(相关例程)
51单片机串口通信1./*打开串口调试程序,将波特率设置为9600,无奇偶校验晶振11.0592MHz,发送和接收使用的格式相同,如都使用字符型格式,在发送框输入hello,I Love MCU ,在接收框中同样可以看到相同字符,说明设置和通信正确*/#include <REG52.H>/*主程序*/void main (void){SCON = 0x50; /* SCON: 模式1, 8-bit UART, 使能接收*/TMOD |= 0x20; /* TMOD: timer 1, mode 2,8-bit reload*/TH1 = 0xFD; /* TH1: **********************************/ TR1 = 1; /* TR1: timer 1 run */EA = 1; /*打开总中断*/ES = 1; /*打开串口中断*/while (1) /*主循环不做任何动作*/{}}void UART_SER (void) interrupt 4 //串行中断服务程序{unsigned char Temp; //定义临时变量if(RI) //判断是接收中断产生{RI=0; //标志位清零Temp=SBUF; //读入缓冲区的值P1=Temp; //把值输出到P1口,用于观察SBUF=Temp; //把接收到的值再发回电脑端}if(TI) //如果是发送标志位,清零TI=0;}2.51单片机与电脑串口通信的C程序,最好是中断方式的#include <reg51.h>#include <string.h>unsigned char ch;bit read_flag= 0 ;void init_serialcom( void ) //串口通信初始设定{SCON = 0x50 ; //UART为模式1,8位数据,允许接收TMOD |= 0x20 ; //定时器1为模式2,8位自动重装PCON |= 0x80 ; //SMOD=1;TH1 = 0xFD ; //Baud:19200 fosc="11".0592MHzIE |= 0x90 ; //Enable Serial InterruptTR1 = 1 ; // timer 1 run}//向串口发送一个字符void send_char_com( unsigned char ch){SBUF=ch;while (TI== 0);TI= 0 ;}void serial () interrupt 4 using 3 //串口接收中断函数{if (RI){RI = 0 ;ch=SBUF;read_flag= 1 ; //就置位取数标志}}main(){init_serialcom(); //初始化串口while ( 1 ){if (read_flag) //如果取数标志已置位,就将读到的数从串口发出{read_flag= 0 ; //取数标志清0send_char_com(ch);}}}3.// 单片机串行口发送/接收程序,每接收到字节即发送出去// 和微机相接后键入的字符回显示在屏幕上// 可用此程序测试#include <reg51.h>#define XTAL 11059200 // CUP 晶振频率#define baudrate 9600 // 通信波特率void main(void){unsigned char c;TMOD = 0x20; // 定时器1工作于8位自动重载模式, 用于产生波特率TH1=(unsigned char)(256 - (XTAL / (32L * 12L * baudrate)));TL1=(unsigned char)(256 - (XTAL / (32L * 12L * baudrate))); // 定时器0赋初值SCON = 0x50;PCON = 0x00;TR1 = 1;IE = 0x00; // 禁止任何中断{while(RI == 0);RI = 0;c = SBUF; // 从缓冲区中把接收的字符放入c中SBUF = c; // 要发送的字符放入缓冲区while(TI == 0);TI = 0;}}4.//////////////// ///////////////////////////////////////////////////////////E51Pro.c//Easy 51Pro编程器主程序,负责通讯,管理编程操作/////////////////////////////////////////////////////////////////////////#include <E51Pro.h>BYTE ComBuf[18];//串口通讯数据缓存,发送和接收都使用UINT nAddress;//ROM中地址计数UINT nTimeOut;//超时计数ProWork pw;//编程器一般操作void Delay_us(BYTE nUs)//微秒级延时<255us{TH0=0;TL0=0;TR0=1;while(TL0<nUs)//利用T0做定时计数器,循环采样,直到达到定时值{}TR0=0;}void Delay_ms(UINT nMs)//豪秒级的延时<65535ms{UINT n=0;TR0=1;while(n<nMs)////利用T0做定时计数器,循环采样,直到达到定时值{TH0=0;TL0=20;while(TH0<4){}n++;}TR0=0;}BOOL WaitComm()//等待上位机的命令,18字节{RI=0;while(!RI){}//等待第一个字节ComBuf[n]=SBUF;RI=0;n++;for(n;n<=17;n++){nTimeOut=0;while(!RI){nTimeOut++;if(nTimeOut>10000)//后17个字节都有超时限制return 0;}ComBuf[n]=SBUF;RI=0;}return 1;}BOOL WaitResp()//等待上位机回应,1字节,有超时限制{nTimeOut=0;RI=0;while(!RI){nTimeOut++;if(nTimeOut>50000){return 0;}}RI=0;ComBuf[0]=SBUF;return 1;}BOOL WaitData()//写器件时等待上位机数据,18字节,有超时限制{BYTE n;RI=0;for(n=0;n<=17;n++){nTimeOut=0;while(!RI){nTimeOut++;if(nTimeOut>10000){return 0;}}RI=0;ComBuf[n]=SBUF;}return 1;}void SendData()//发送数据或回应操作完成,18字节{BYTE n=0;for(n;n<=17;n++){TI=0;SBUF=ComBuf[n];while(!TI){}TI=0;}}void SendResp()//回应上位机1个字节,在写器件函数中使用{TI=0;SBUF=ComBuf[0];while(!TI){}TI=0;}void SetVpp5V()//设置Vpp为5v{P3_4=0;P3_3=0;}void SetVpp0V()//设置Vpp为0v{P3_3=0;P3_4=1;}void SetVpp12V()//设置Vpp为12v{P3_4=0;P3_3=1;}void RstPro()//编程器复位{pw.fpProOver();//直接编程结束SendData();//通知上位机,表示编程器就绪,可以直接用此函数因为协议号(ComBuf[0])还没被修改,下同}void ReadSign()//读特征字{pw.fpReadSign();SendData();//通知上位机,送出读出器件特征字}void Erase()//擦除器件{pw.fpErase();SendData();//通知上位机,擦除了器件}void Write()//写器件{BYTE n;pw.fpInitPro();//编程前的准备工作SendData();//回应上位机表示进入写器件状态,可以发来数据while(1){if(WaitData())//如果等待数据成功{if(ComBuf[0]==0x07)//判断是否继续写{for(n=2;n<=17;n++)//ComBuf[2~17]为待写入数据块{if(!pw.fpWrite(ComBuf[n]))//<<< <<<<<<调用写该器件一个单元的函数{pw.fpProOver();//出错了就结束编程ComBuf[0]=0xff;SendResp();//回应上位机一个字节,表示写数据出错了WaitData();//等待上位机的回应后就结束return;}nAddress++;//下一个单元}ComBuf[0]=1;//回应上位机一个字节,表示数据块顺利完成,请求继续SendResp();}else if(ComBuf[0]==0x00)//写器件结束break;else//可能是通讯出错了{pw.fpProOver();return;}}else//等待数据失败{pw.fpProOver();return;}}pw.fpProOver();//编程结束后的工作Delay_ms(50);//延时等待上位机写线程结束ComBuf[0]=0;//通知上位机编程器进入就绪状态SendData();}void Read()//读器件{BYTE n;pw.fpInitPro();//先设置成编程状态SendData();//回应上位机表示进入读状态while(1){if(WaitResp())//等待上位机回应1个字节{if(ComBuf[0]==0)//ComBuf[0]==0表示读结束{break;}else if(ComBuf[0]==0xff)//0xff表示重发{nAddress=nAddress-0x0010;}for(n=2;n<=17;n++)//ComBuf[2~17]保存读出的数据块{ComBuf[n]=pw.fpRead();//<<<<<<<<<<调用写该器件一个单元的函数nAddress++;//下一个单元}ComBuf[0]=6;//向上位机发送读出的数据块SendData();}elsebreak;//等待回应失败}pw.fpProOver();//操作结束设置为运行状态ComBuf[0]=0;//通知上位机编程器进入就绪状态SendData();}void Lock()//写锁定位{pw.fpLock();SendData();}///////////////////////////////////////////////////////////////////////////////////所支持的FID,请在这里继续添加/////////////////////////////////////////////////////////////////////////////extern void PreparePro00();//FID=00:AT89C51编程器extern void PreparePro01();//FID=01:AT89C2051编程器extern void PreparePro02();//FID=02:AT89S51编程器void main(){SP=0x60;SetVpp5V();//先初始化Vpp为5vSCON=0x00;TCON=0x00;//PCON=0x00;//波特率*2IE=0x00;//TMOD: GATE|C/!T|M1|M0|GATE|C/!T|M1|M0// 0 0 1 0 0 0 0 1TMOD=0x21;//T0用于延时程序TH1=0xff;TL1=0xff;//波特率28800*2,注意PCON//SCON: SM0|SM1|SM2|REN|TB8|RB8|TI|RI// 0 1 0 1 0 0 0 0SCON=0x50;TR1=1;Delay_ms(1000);//延时1秒后编程器自举ComBuf[0]=0;SendData();while(1)//串口通讯采用查询方式{if(!WaitComm())//如果超时,通讯出错{Delay_ms(500);ComBuf[0]=0;//让编程器复位,使编程器就绪}switch(ComBuf[1])//根据FID设置(ProWork)pw中的函数指针{case 0: //at89c51编程器PreparePro00(); break;case 1: //at89c2051编程器PreparePro01(); break;case 2: //at89s51编程器PreparePro02(); break;//case 3:支持新器件时,请继续向下添加// break;//case 4:// break;default: ComBuf[0]=0xff;ComBuf[1]=0xff; //表示无效的操作break;}switch(ComBuf[0])//根据操作ID跳到不同的操作函数{case 0x00:RstPro();break; / /编程器复位case 0x01:ReadSign();break; //读特征字case 0x02:Erase();break;//擦除器件case 0x03:Write();break;//写器件case 0x04:Read();break;//读器件case 0x05:Lock();break;//写锁定位default: SendData();break;}}}5.v oid InitSerial(void){TMOD = 0x20; // T1 方式2PCON=0x00; // PCON=00H,SMOD=0 PD = PCON.2 = 1 进入掉电模式TH1 = TL1 = BAUD_9600; // BAUD: 9600SCON = 0x50; // 串行通信方式1 REN=1 允许接收ET1 = 0; // 不允许中断TR1 = 1; // 开启定时器1IE = 0; // 关闭所有中断允许位memset(&SerialBuf, 0x00, SERIAL_BUF_LEN); // 初始化SerialBuf[SERIAL_BUF_LEN] }/**********************************************************名称:SendByte()**功能:串口发送一个字节**输入:ucData**返回:无**说明:无********************************************************/void SendByte(unsigned char ucData){SBUF = ucData;while(!TI){_CLRWDT_;}TI = 0;}RS232串口通信程序#include <AT89X52.H>unsigned char code dispcode1[]={" welcome! "}; unsigned char code dispcode2[]={""}; unsigned char i,j,k,l,DData;sbit RS = P3^5;sbit RW = P3^6;sbit E = P3^7;unsigned char m=0;void delay(){for(l=0;l<=100;l++){}}void enable() //write order{RS=0;RW=0;E=0;delay();E=1;}void enable2() //write data{RS=1;RW=0;E=0;delay();E=1;}void initializtion() //lcd initializtion{for(i=0;i<=100;i++)P0=0x01;enable();P0=0x38;enable();P0=0x0f;enable();P0=0x06;enable();}void Display(m,DData) // display data{P0=0xC0+m; //write addressenable();P0=DData; //write dataenable2();}void Esisr() interrupt 4 //串口接收中断服务程序{unsigned char temp;ES=0;if(RI == 1){RI = 0;temp = SBUF; //接收数据SBUF=temp; //将接收到的数据发送至PC机Display(m,temp); //将接收到的数据送LCD显示while(!TI); //等待数据发送完成TI=0;m++;if(m>16)m=0;}ES=1;}void system_initial(void) //system initializtion{TMOD=0x21;// 定时器1工作方式2,定时器0工作方式1PCON=0x00;//数据传输率选择。
51单片机串并口转换实验
我也是刚入手单片机,今天编了一段小程序,就是关于单片机串口转并口和并口转串口的一个小实验,本程序在PTOTUES中完美运行。
在单片机开发试板上也是完美运行。
今天贴出来供大家分享,看完本历程,有助于提高您对单片机IO口的基本操作,锁存器的用法以及串并转换的使用技能#include<reg52.h>本例程的电路连接图如上,在电路中使用了AT89C51单片机一块,74HC595八路串/并转换器,74HC165八路并串转换器和一片74HC573 锁存器。
实验者请按上图连接好实验电路。
#include<reg52.h>#include< intrins.h >#define uchar unsigned char#define uint unsigned int#define ulong unsigned longcode uint a[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};sbit SO=P1^0; //定义165的输出sbit STCP=P1^1;sbit DS=P1^2;sbit SHCP=P1^3;sbit SHLD=P1^4;sbit CLK=P1^5;sbit cs573=P1^6;/**************************************************/void delay(ulong X) //延时函数,采用了形参传递函数{while(X--);}/**************************************************/void LED(); //函数声明/**************************************************/void main() //主函数{while(1){LED ();}}/****************************************************/void LED(){uint i,j,k;uchar n,m;for(i=0;i<8;i++){cs573=1;P2=a[i]; //往P2口送流水灯字符,因为有8个流水灯,所以i=8循环八次,LED小灯依次被点亮cs573=0; //把P2口送过来的数据锁存SHLD=0; //74HC165开始装载数据delay(10);SHLD=1;for(j=0;j<8;j++) //开始八次循环移位{n<<=1;delay(10);CLK=0;n|=SO;delay(10);CLK=1;}P3=n;m=n;for(k=0;k<8;k++) //74HC595开始转换数据{SHCP=0;if((m&0x80)==0x80)DS=1;elseDS=0;m<<=1;SHCP=1;delay(300);}STCP=0;STCP=1;delay(30000);}}。
C51单片机串口通讯通用模块代码(可用于操作系统串口通讯)
C51单片机串口通讯通用模块代码(可用于操作系统串口通讯)#include#include "UART1.h"#include "commdriver.h"//当前适用于C51//可以根据具体CPU型号,修改宏定义和串口初始化代码就可以#define CPU_XTAL 22118400 //CPU频率#define FUNCTION_NULL 0 //没有定义函数#define COM_TI TI //发送中断寄存器#define COM_TI0() {TI = 0;} //发送中断寄存器清零#define COM_TI1() {TI = 1;} //发送中断寄存器置一( 强行置一触发发送中断)#define COM_TI_SBUF(dat) {SBUF = dat;} //发送数据到硬件缓冲区#define COM_TI_End() {return;} //发送结束处理函数#define COM_RI RI //接收中断寄存器#define COM_RI0() {RI = 0;} //接收中断寄存器清零#define COM_RI1() {RI = 1;} //接收中断寄存器置一#define COM_RI_SBUF(dat) {dat = SBUF;} //提取接收硬件缓冲区数据#define COM_TI_FLAG COM_TI //发送中断标志寄存器(非中断发送方式使用)#define COM_TI_FLAG0() COM_TI0() //发送中断标志寄存器清零(非中断发送方式使用)void (*COM1RevEvent)(unsigned char dat); //数据接收事件#define LenTxBuf 30 //发送缓冲区长度#define LenRxBuf 1 //接收缓冲区长度volatile unsigned char TxBuf1[LenTxBuf],RxBuf1[LenRxBuf]; //收发缓冲区实体volatile unsigned char *inTxBuf1,*outTxBuf1,*inRxBuf1,*outRxBuf1; //收发缓冲区读写指针volatile unsigned char TIflag1=1;//Note:It must be 1. //发送缓冲区为空标志//*********************#define _TxBuf TxBuf1#define _RxBuf RxBuf1#define _inTxBuf inTxBuf1#define _outTxBuf outTxBuf1#define _inRxBuf inRxBuf1#define _outRxBuf outRxBuf1#define _TIflag TIflag1/*************函数声明****************/#define _COMRevEvent COM1RevEvent //串口接收事件#define _USART_IRQ void USART1_IRQHandler(void) interrupt 4 //串口中断服务程序#define _COM_Buffer_Init void COM1_Buffer_Init(void) //串口缓冲区初始化#define _COM_Open void COM1_Open(unsigned int baudrate,void (*revevent)(unsigned char dat)) // 串口初始化#define _COM_Close void COM1_Close(void) //关闭串口#define _COM_GetOneByte unsigned charCOM1_GetOneByte(unsigned char *ch) //获取一个字节#define _COM_GetPChar unsigned char COM1_GetPChar(unsigned char *ch,unsigned char len) //获取指定长度字节数组#define _COM_RxByte unsigned char COM1_RxByte(void) //获取接收字节个数//********缓冲区中断方式发送(安全性高)#define _COM_SendOneByte unsigned char COM1_SendOneByte(unsigned char one_byte) // 发送一个字节#define _COM_SendPChar void COM1_SendPChar(unsigned char *P,unsigned char Len) //发送定长字节数组#define _COM_SendString void COM1_SendString(unsigned char *P) //发送字符串//********非缓冲区中断方式发送#define _COM_PrintOneByte void COM1_PrintOneByte(unsigned char c) // 发送一个字节#define _COM_PrintPChar void COM1_PrintPChar(unsigned char *buf,unsigned int len) //发送定长字节数组#define _COM_PrintString void COM1_PrintString(unsigned char *P) //发送字符串//*************内部引用模型函数(外部不关心,移植时修改后面函数名,要与上面对应的外部声明的函数名一致)*******************#define COM_GetOneByte_(ptr) COM1_GetOneByte(ptr) //与上面获取一个字节的函数对应#define COM_SendOneByte_(dat) COM1_SendOneByte(dat) //与上面发送一个字节的函数对应#define COM_PrintOneByte_(dat) COM1_PrintOneByte(dat) //与上面发送一个字节的函数对应//*********************函数模型定义区(不需要修改)*****************/****************************函数模型:void USART_IRQHandler(void)函数功能:串口中断服务程序入口参数:无返回值:无修改者:修改时间:修改内容简要:***************************/_USART_IRQ //串口1中断{volatile unsigned char *t;if(COM_RI){COM_RI0(); //清接收标记if(_COMRevEvent != FUNCTION_NULL) //自定义接收事件{COM_RI_SBUF(*_inRxBuf);_COMRevEvent(*_inRxBuf);}else{t = _inRxBuf;t++;if(t == (_RxBuf + LenRxBuf)) t = _RxBuf;if(t != _outRxBuf) //RxBuf No Full{COM_RI_SBUF(*_inRxBuf);_inRxBuf = t;}}}if(COM_TI){COM_TI0();if(_inTxBuf == _outTxBuf) {_TIflag = 1;COM_TI_End();};//TxBuf1 EmptyCOM_TI_SBUF(*_outTxBuf); _outTxBuf++;if(_outTxBuf == (_TxBuf+LenTxBuf)) _outTxBuf = _TxBuf;}}/****************************函数模型:void COM1_Buffer_Init(void)函数功能:串口1缓冲区初始化入口参数:无返回值:无修改者:修改时间:修改内容简要:***************************/_COM_Buffer_Init{_inTxBuf = _TxBuf;_outTxBuf = _TxBuf;_inRxBuf = _RxBuf;_outRxBuf = _RxBuf;}/****************************函数模型:void COM_Open(unsigned int baudrate,void (*revevent)(unsigned char dat))函数功能:系统串口初始化入口参数: unsigned int baudrate:串口波特率返回值:无修改者:修改时间:修改内容简要:***************************/_COM_Open{//定时器1做波特率发生器TI = 0; /* clear transmit interrupt */TR1 = 0; /* stop timer 1 */ET1 = 0; /* disable timer 1 interrupt */PCON |= 0x80; /* 0x80=SMOD: set serial baudrate doubler */ TMOD &= ~0xF0; /* clear timer 1 mode bits */TMOD |= 0x20; /* put timer 1 into MODE 2 */TH1 = (unsigned char) (256 - (CPU_XTAL / (16L * 12L * baudrate)));TR1 = 1; /* start timer 1 *///设置串口1模式SM0 = 0; SM1 = 1; /* serial port MODE 1 */SM2 = 0;REN = 1; /* enable serial receiver */RI = 0; /* clear receiver interrupt */TI = 0; /* clear transmit interrupt */ES = 1; /* enable serial interrupts */PS = 1; /* set serial interrupts to low priority */_COMRevEvent = revevent;}/****************************函数模型:void COM1_Close(void)函数功能:关闭系统串口入口参数:无返回值:无修改者:修改时间:修改内容简要:***************************/_COM_Close{}/****************************函数模型:unsigned char COM1_GetOneByte(unsigned char *ch)函数功能:获取一个字节入口参数:unsigned char *ch:接收字节指针返回值: unsigned char *ch:接收字节指针unsigned char :获取状态;0:成功,1:失败(缓冲区为空)修改者:修改时间:修改内容简要:***************************/_COM_GetOneByte{if(_inRxBuf == _outRxBuf) {return 0;}; //RxBuf Empty*ch = *_outRxBuf; _outRxBuf++;if(_outRxBuf==_RxBuf+LenRxBuf) _outRxBuf = _RxBuf;return 1;}/****************************函数模型:unsigned char COM_GetPChar(unsigned char *ch,unsigned char len)函数功能:获取指定长度字节数组入口参数: unsigned char *ch:接收字节数组指针unsigned char len:接收字节个数返回值: unsigned char *ch:接收字节数组指针unsigned char:实际接收字节个数修改者:修改时间:修改内容简要:***************************/_COM_GetPChar{unsigned char i = 0;do{len--;if(!COM_GetOneByte_(ch)) break;i++;ch++;}while(len);return i;}/****************************函数模型:unsigned char COM_RxByte(void)函数功能:获取接收缓冲区有效字节个数入口参数:无返回值: unsigned char:接收缓冲区有效字节个数修改者:修改时间:修改内容简要:***************************/_COM_RxByte{if(_inRxBuf>=_outRxBuf) return (_inRxBuf-_outRxBuf);else return LenRxBuf-(_outRxBuf-_inRxBuf);}/****************************函数模型:unsigned char COM_SendOneByte(unsigned char one_byte)函数功能:发送一个字节入口参数: unsigned char one_byte:发送的字节返回值:unsigned char:发送状态,0:成功,1:失败(缓冲区满)修改者:修改时间:修改内容简要:***************************/_COM_SendOneByte{volatile unsigned char *t;if(_TIflag){_TIflag = 0;COM_TI1();}t = _inTxBuf;t++;if(t == _TxBuf + LenTxBuf) t = _TxBuf;if(t == _outTxBuf) {return 1;};//TxBuf Full*_inTxBuf = one_byte;_inTxBuf = t;return 0;}/****************************函数模型:void COM_SendPChar(unsigned char *P,unsigned char Len)函数功能:发送定长字节数组入口参数: unsigned char *P:字节数组指针unsigned char Len:发送长度返回值:无修改者:修改时间:修改内容简要:***************************/_COM_SendPChar{while(Len){//while(COM1_SendOneByte(*P)); //发送失败,继续发送,知道发送成功COM_SendOneByte_(*P);P++;Len--;}}/****************************函数模型:void COM_SendString(unsigned char *P)函数功能:发送字符串入口参数: unsigned char *P:字符串指针返回值:无修改者:修改时间:修改内容简要:***************************/_COM_SendString{while(*P){COM_SendOneByte_(*P);P++;}}//**************** 非缓冲区中断方式发送/****************************函数模型:void COM_PrintOneByte(unsigned char c)函数功能:发送一个字节入口参数: unsigned char one_byte:发送的字节返回值:无修改者:修改时间:修改内容简要:***************************/_COM_PrintOneByte{COM_TI_FLAG0();COM_TI_SBUF(c); //发送数据while(!COM_TI_FLAG) ; //等待发送结束}/****************************函数模型:void COM_PrintPChar(unsigned char *buf,unsigned int len)函数功能:发送定长字节数组入口参数: unsigned char *P:字节数组指针unsigned char Len:发送长度返回值:无修改者:修改时间:修改内容简要:***************************/_COM_PrintPChar{while(len){COM_PrintOneByte_(*buf);buf ++;len--;}}/****************************函数模型:void COM_PrintString(unsigned char *P) 函数功能:发送字符串入口参数: unsigned char *P:字符串指针返回值:无修改者:修改时间:修改内容简要:***************************/_COM_PrintString{while(*P){COM_PrintOneByte_(*P);P++;}}。
51单片机串口变并口汇编程序
51单片机串口变并口汇编程序51单片机是一种常用的微控制器,它具有高性能、低功耗、丰富的外设和广泛的应用领域。
其中,串口和并口是常见的通信接口方式。
本文将详细介绍51单片机串口变并口汇编程序的实现方法。
## 1. 串口和并口介绍### 1.1 串口串行通信接口(Serial Communication Interface),简称串口,是一种将数据以连续位的形式传输的通信方式。
它只需要两根线(发送线和接收线)即可实现数据传输,适用于远距离传输和多设备连接。
### 1.2 并口并行通信接口(Parallel Communication Interface),简称并口,是一种将数据以多个位同时传输的通信方式。
它需要多根线同时传输数据,适用于高速数据传输和短距离连接。
## 2. 串行通信与并行通信转换原理在51单片机中,通过软件编程可以实现串行通信与并行通信之间的转换。
下面是其基本原理:### 2.1 串行转并行在将串行数据转换为并行数据时,需要一个移位寄存器来存储接收到的串行数据,并通过时钟信号按位移出到并行总线上。
具体步骤如下:1. 初始化串口参数,包括波特率、数据位、停止位等。
2. 等待串口接收到数据。
3. 将接收到的串行数据写入移位寄存器。
4. 通过时钟信号依次将移位寄存器中的数据按位移出到并行总线上。
### 2.2 并行转串行在将并行数据转换为串行数据时,需要一个移位寄存器来存储要发送的并行数据,并通过时钟信号按位读取并发送出去。
具体步骤如下:1. 初始化串口参数,包括波特率、数据位、停止位等。
2. 将要发送的并行数据写入移位寄存器。
3. 通过时钟信号依次从移位寄存器中读取数据,并发送出去。
## 3. 51单片机串口变并口汇编程序实现下面是一个示例程序,演示了如何在51单片机中实现串口变并口的功能。
```assembly; 定义串口接收和发送函数USART_Rx: ; 串口接收函数MOV A, SBUF ; 读取SBUF中的接收数据RETUSART_Tx: ; 串口发送函数MOV SBUF, A ; 将A寄存器中的数据写入SBUFRET; 主程序入口MAIN:MOV TMOD, #20H ; 设置定时器1为工作模式2,用于串口通信 MOV TH1, #FDH ; 设置波特率为9600SETB TR1 ; 启动定时器1; 初始化串口参数MOV SCON, #50H ; 设置串口工作模式为8位数据位、1位停止位、可变波特率; 接收数据并转换为并行数据发送CALL USART_Rx ; 调用串口接收函数,将接收到的数据存入A寄存器MOV P0, A ; 将A寄存器中的数据写入P0,并行总线; 并行数据转换为串行数据发送MOV A, P1 ; 从P1并行总线读取要发送的数据,存入A寄存器CALL USART_Tx ; 调用串口发送函数,将A寄存器中的数据发送出去SJMP MAIN ; 无限循环END```上述汇编程序通过调用USART_Rx和USART_Tx函数实现了串口接收和发送功能。
C51单片机和电脑串口通信电路图
C51单片机和电脑串口通信电路图与源码51单片机有一个全双工的串行通讯口,所以单片机和电脑之间可以方便地进行串口通讯。
进行串行通讯时要满足一定的条件,比如电脑的串口是RS232电平的,而单片机的串口是TTL电平的,两者之间必须有一个电平转换电路,我们采用了专用芯片MAX232进行转换,虽然也可以用几个三极管进行模拟转换,但是还是用专用芯片更简单可靠。
我们采用了三线制连接串口,也就是说和电脑的9针串口只连接其中的3根线:第5脚的GND、第2脚的RXD、第3脚的TXD。
这是最简单的连接方法,但是对我们来说已经足够使用了,电路如下图所示,MAX232的第10脚和单片机的11脚连接,第9脚和单片机的10脚连接,第15脚和单片机的20脚连接.串口通讯的硬件电路如上图所示在制作电路前我们先来看看要用的MAX232,这里我们不去具体讨论它,只要知道它是TTL和RS232电平相互转换的芯片和基本的引脚接线功能就行了。
通常我会用两个小功率晶体管加少量的电路去替换MAX232,可以省一点,效果也不错,下图就是MAX232的基本接线图。
按图7-3加上MAX232就可以了。
这大热天的拿烙铁焊焊,还真的是热气迫人来呀:P串口座用DB9的母头,这样就可以用买来的PC串口延长线进行和电脑相连接,也可以直接接到电脑com口上。
为了能够在电脑端看到单片机发出的数据,我们必须借助一个WINDOWS软件进行观察,这里我们利用一个免费的电脑串口调试软件。
本串口软件在本网站可以找到软件界面如上图,我们先要设置一下串口通讯的参数,将波特率调整为4800,勾选十六进制显示。
串口选择为COM1,当然将网站提供的51单片机实验板的串口也要和电脑的COM1连接,将烧写有以下程序的单片机插入单片机实验板的万能插座中,并接通51单片机实验板的电源。
#include <reg51。
h〉#define BUFFERLEGTH 10//-—---———-—-——————--——-----—--——--——------—-—--—-—--—--——-———-—--—void UART_init();//串口初始化函数void COM_send(void);//串口发送函数char str[20];char j;//——-----————---——-—--—--—-—-—-———-———-—-——-—--—-—-——————--———-—--———void main(void){unsigned char i;UART_init();j=0; //初始化串口for(i = 0;i < 10 ;i++){COM_send(); //首先发送一次数据作为测试用};while(1);}//-——-——-——---------———-——-—-—-——--—---—---—--—-—--——---—---—--//——-——--——--—-—-—--———————---—-——-——-———-—-----——--—---——————-—-—-—-—————-—--—-—---—--———-——---——-- // 函数名称:UART_init()串口初始化函数// 函数功能: 在系统时钟为11.059MHZ时,设定串口波特率为9600bit/s// 串口接收中断允许,发送中断禁止//—-——--—-----———---—-——-—-——————-————-—-————---——-———————--———-———----—-—--—---——-—---—-————-———---void UART_init(){//初始化串行口和波特率发生器SCON =0x50; //选择串口工作方式1,打开接收允许TMOD =0x20; //定时器1工作在方式2,定时器0工作在方式1TH1 =0xfA; //实现波特率9600(系统时钟11。
利用串口与并口实现51内核单片机的在线编程
利用串口与并口实现51内核单片机的在线编程
张懿
【期刊名称】《单片机与嵌入式系统应用》
【年(卷),期】2005(000)003
【摘要】详细说明利用并口模拟I2C总线协议,实现Myson MTV230芯片的在线编程(ISP)过程,以及利用PC机的串口通信实现Winbond W78E516B的在线编程(ISP)过程;阐述PC机的串口与并口在单片机开发中的应用.
【总页数】4页(P32-35)
【作者】张懿
【作者单位】浙江大学
【正文语种】中文
【中图分类】TP368.1
【相关文献】
1.用单片机实现并口到串口的数据存储与转发 [J], 孙海善;孙承达
2.基于FPGA的多串口51单片机的设计与实现 [J], 魏绪文
3.通过PROTEUS软件实现ICL7135与51单片机串口仿真 [J], 王忠远;张凤桐;
4.51单片机与PC机串口通信的仿真与实现 [J], 李健
5.MCS-51单片机上实现多串口通讯的技术分析 [J], 张英
因版权原因,仅展示原文概要,查看原文内容请购买。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
利用串口与并口实现51内核单片机的在线编程摘要:详细说明利用并口模拟I2C总线协议,实现Myson MTV230芯片的在线编程(ISP)过程,以及利用PC机的串口通信实现Winbond W78E516B的在线编程(ISP)过程;阐述PC机的串口与并口在单片机开发中的应用。
关键词:并口编程串口通信在线编程ISP MTV230 W78E516B引言1 在线编程简介51内核的单片机在线编程模式一般分为两大类。
一类是使用JTAG协议的在线编程模式。
这类模式一般由厂家提供在线编程工具,使用方便。
使用这一类模式的单片机价格往往较高,使用的厂商也不多,故不在本文的讨论之列。
另一类在线编程模式是使用一条特殊的指令,使单片机进入在线编程模式。
在进入在线编程模式后,要自己控制对单片机的擦除写入逻辑。
这一类模式又可细分为两种不同的模式:一是进入在线编程模式后,单片机只是提供一个接口,不再运行用户的程序,擦写逻辑全由上位机(PC)提供,如以下要讨论的MTV230就属于这种模式;另一类是进入在线编程模式以后,芯片会运行在某一区域的用户编写的程序,芯片的编程逻辑都由芯片中这段程序控制,上位机(PC)只是作为单片机的一个数据源,向单片机传输要擦写的数据,如以下要讨论的W78E516B。
2 利用并口对MTV230在线编程的实现2.1 MTV230简介MTV230是由Myson公司出品的一块集成OSD功能的基于51内核的芯片。
它使用1 2MHz晶振时可以设置为倍频工作,同时还集成了4路A/D和4路PWM DAC。
其中最具竞争力的便是它使用了Flash OSD字库。
与一般的OSD芯片不同,它的字库不是掩膜在芯片中,用户可以自己定制。
该款芯片可以满足视频应用中的控制需求,因而被广泛应用于视频类产品中。
2.2 MTV230在线编程模式的进入要使MTV230具有在线编程的功能,可以添加一段程序在主应用程序中。
该程序用来响应特定的单片机状态,如某一特定引脚的电平变化,或是串口接收到特定的字符以确定是否要进入在线编程模式。
在执行以下程序后,MTV230可以进入在线编程模式[1]:①清看门狗,以防止在编程期间单片机被复位;②单片机的在线编程模式是在空闲状态(idle)下进行的,所以要关闭所有中断,防止单片机被唤醒;③由于MTV230在线编程时是作为I2C的从设备,因而要配置单片机的I2C从地址;④向ISPEN写入0x93,使能在线编程功能;⑤进入51的空闲模式,在线编程开始。
具体程序如下:WDT=0; //1IE=0; //2ISPSLV=0x7C; //3ISPEN=0x93; //4PCON=0x01; //5以上程序中1~5与上述说明对应。
以上将I2C地址设置为0x7C。
值得注意的是,设置I2C从地址时,最低两位无效[1]。
执行完以上程序,单片机已经变为一个I2C从设备,将I2C中SCL与芯片的15脚相连,SDA与芯片的16脚相连,就可以用I2C协议,按一定的命令格式对芯片进行在线编程。
命令格式详见参考文献[1],在此不再赘述。
2.3 PC机I2C接口的实现对MTV230进行在线编程,就要实现I2C通信协议。
作为对MTV230进行编程的上位机P C来说,实现I2C有三种方法:①使用串口与单片机通信,再由单片机模拟I2C协议,成本高,I2C速度视使用的单片机而定;②对计算机的并口编程,模拟I2C协议,成本低,I2C速度一般;③使用USB接口实现I2C协议,成本高,I2C速度快市场上可以买到。
由于MTV230进行编程时,I2C时钟速度最高为140kHz,速度要求不高,同时考虑到成本,决定使用方案②。
2.4 并口I2C硬件的实现由于并口的每个引脚都是单向的,只能单向输出或者单向输入;而I2C又是一个双向协议,SDA与SCL都要求既能输入又能输出(有时要获取SCL当前状态),所以,SDA与SCL要分别各由一个输出引脚与一个输入引脚构成。
为了增加并口的驱动能力与可靠性,设计电路如图1所示。
其中并口的2、12引脚构成SDA脚,并口的3、10引脚构成SCL脚。
2.5 并口I2C软件的实现在Win98中对并口的编程非常简单,通过在VC中内嵌汇编,使用IN与OUT指令访问与并口相对应的端口,设置相对应端口的值中的位就可以控制相应并口引脚的高低电平值。
例如:要将计算机并口1的第2引脚先置高再置低,汇编语言可以这样写:MOV DX ,0x378 ;设置端口地址MOV AL ,1 ;将待写入的位0的值写入AL中OUT DX ,AL ;将值送到相应端口MOV AL ,0OUT DX ,AL但在Win2000/XP中,由于系统加强了对硬件设备的保护,假如在程序中直接用IN与OU T指令访问并口,则会引发系统的非法操作;而并口访问又不像串口,直接可以使用Wind ows API函数,因而就必须使用驱动程序。
可以到网站上去下载DriverLI NX Port I/O Driver并口驱动程序。
该程序可以免费复制与分发。
有了这个驱动程序,在W in2000/XP下编写并口程序就十分方便。
安装该驱动程序后,在程序中包含相应的dlportio. h与dlportio.lib后就可以用DlPortReadPortUchar(IN ULONG Port)来读取端口的值(相当于汇编中的IN指令),用DlPortWritePortUchar(IN ULONG Port,IN UCHAR Value)来向一个端口写一个特定的值(相当于汇编中的OUT指令)。
利用改变端口值中的一个位的值,可以使相应并口引脚输出高低电平,从而可以用其来模拟I2C协议,实现并口与单片机间的I2C通信。
关于I2C协议,网上有很多资料,在此不再赘述。
2.6 程序说明如前文所述,MTV230在进入在线编程模式后,就相当于一个I2C从设备,编程逻辑全都由在PC上运行的程序来实现。
该程序采用VC6.0编写。
编程程序的主界面如图2所示,主要模块如表1所列。
由于用并口模拟I2C对单片机编程,会使该线程暂时处在阻塞状态,假如在主线程(UI)中实现该过程,则在对芯片编程时,程序的主界面就无法响应用户退出命令,所以采用了多线程程序结构,在一个工作线程实现该过程,使用户可以随时退出编程过程。
表1所列的头三个类采用了层次设计结构:上层类调用下层类,下层类为上层类提供接口,这样设计保证了代码的最大可重用性。
举例来说,假如有另一芯片同样是使用I2C 接口进行在线编程,则只要重写MTVISP这个芯片的在线编程协议类就可以了;如果使用前面所述的并口实现方案1或3,只要重写最底层的Parallel类便可。
程序工作线程的大致流程如图3所示。
程序的特色:①可以自己设置I2C速度的高低,模拟I2C的并口地址,以及使用并口的引脚。
②可以选择简单校验和完全校验,即对编程后的芯片是进行内部校验寄存器值的简单校验,还是将芯片中的内容全部读出与编程文件进行比较的完全校验。
③可以对芯片内的程序区、OSD区进行编程,还可以读出这两区的数据(只有对可以设定进入在线编程模式的程序才可以)。
④进行烧写的文件支持二进制文件格式(*.bin)与Intel的Hex文件格式(*.hex)。
3 利用串口对W78E516B在线编程的实现3.1 W78E516B简介W78E516B是由Winbound公司出品的基于52内核的高性能芯片,外部晶振可以达到40 MHz,内部具有64KB的程序区与4KB的引导程序区,以及256B的RAM区和256B的A UX-RAM区。
AUX-RAM区相当于外部存储区,进行寄存器设置后,用MOVX指令进行访问。
在Keil编译器中,进行相应的设置便可使用pdata类型变量访问。
3.2 W78E516B在线编程模式的进入W78E516B在线编程模式的进入可以分为两种模式:一种为软件模式,另一种为硬件模式。
当芯片进入在线编程模式后,芯片会从现在的64KB程序区跳转到4KB的引导区的0x00地址处去执行程序。
如前文所述,该类型芯片的在线编程逻辑都是由在这4KB引导区中的程序决定的,而上位机(PC)只是为在线编程提供一个数据源。
(1)软件进入模式①向CHPERN寄存器依此写入0x87,0x59开启CHPCON寄存器的写模式。
②关闭中断。
③向CHPCON写入0x03表示进行程序区编程。
④向CHPCRN写入0x00关闭CHPCON寄存器写模式。
⑤设置好定时器为延时12μs引发中断。
⑥将单片机转入空闲模式,开启中断。
例如:将以下程序嵌入主循环中,当串口收到字符“A”时便进入在线编程模式:if(B_Temp==…A‟{//B_Temp中存放从串口接收到的数TR0=0; //停止定时器TH0=TL0=256-250; //设置定时器定时值CHPENR = 0x87; //开启CHPCON写模式CHPENR = 0x59;CHPCON|=0x03; //开启编程功能CHPENR=0x00; //关闭CHPCON写模式TR0=1; //开启定时器PCON=0x01; //转入空闲模式}(2)硬件进入模式如表2所列,将相应引脚设置为相应电平,在进行复位以后也可进入在线编程模式。
值的注意的是,在芯片正常工作时应避免误入在线编程模式,否则后果不堪设想。
表2中L代表低电平,X代表任意电平。
3.3 W78E516B在线编程的实现(1)单片机引导区程序W78E516B在线编程逻辑主要在这部分程序中实现。
在参考文献[2]中的最后有一个示例程序,它是从外部的SRAM中读取数据对64KB程序区进行编程。
将其改写一下,变为从串口读入数据。
对程序区进行更新,大致流程与示例程序相同,代码也大致相同。
有兴趣的朋友可以自行阅读文献[2]中的程序源文件,在此只列出关键的更改处:;使用24MHz晶振;使用WAVE编译程序;其中R3存有待写入数据字节数-1的高16位;其中R4存有待写入数据字节数-1的低16位JMP PROG_D_64KPADJUEST:INC R2 ;将低位地址增加1CJNE R2,#00H,PROG_D_64KINC R1 ;低位进位时将高位增加1MOV SFRAH,R1 ;改变高位地址PROG_D_64K:MOV SFRAL,R2 ;将低位地址放入JNB RI,$ ;从串口接收一个待写入的字节MOV A,SBUFCLR RIMOV SFRFD,A ;将待写入的值放入MOV TCON,#10H ;开启定时器MOV PCON,#01H ;CPU进入IDLE状态(进行编程)CLR C ; 比较R3、R4,看是否写入完成MOV A,R4SUBB A,R2JNZ PADJUESTCLR CMOV A,R3SUBB A,R1JNZ PADJUEST(2)PC机程序PC机程序为单片机提供一个数据源。