利用51单片机实现IO口模拟串口

发布者:茶叶侠最新更新时间:2017-12-29 来源: eefocus关键字:51单片机  IO口  模拟串口 手机看文章 扫描二维码
随时随地手机看文章

有时需要双串口,转贴一篇 地址见下面

IO口模拟串口 1602显示数据位内容  程序可以实现一个51单片机有两个串口

#include

sbit BT_SND =P1^1;
sbit BT_REC =P1^0;

//1602部分引脚定义
sbit LCM_RW =P2^1 ;//定义引脚
sbit LCM_RS =P2^0;
sbit LCM_E =P2^2;
#define LCM_Data P0
#define Busy 0x80 //用于检测LCM状态字中的Busy标识

#define F_TM F0

#define TIMER0_ENABLE   TL0=TH0; TR0=1;
#define TIMER0_DISABLE TR0=0;

void WritEDAtaLCM(unsigned char WDLCM);
void WriteCommandLCM(unsigned char WCLCM,BuysC);
unsigned char ReadDataLCM(void);
unsigned char ReadStatusLCM(void);
void LCMInit(void);
void DisplayOneChar(unsigned char X, unsigned char Y, unsigned char DData);
void DisplayListChar(unsigned char X, unsigned char Y, unsigned char code *DData);
void Delay5Ms(void);
void Delay400Ms(void);

unsigned char code qq[] = {"Receive_Data"};
//unsigned char code tel[] = {"Command:"};

sbit ACC0=    ACC^0;
sbit ACC1=    ACC^1;
sbit ACC2=    ACC^2;
sbit ACC3=    ACC^3;
sbit ACC4=    ACC^4;
sbit ACC5=    ACC^5;
sbit ACC6=    ACC^6;
sbit ACC7=    ACC^7;

void IntTimer0() interrupt 1
{
F_TM=1;
}

//发送一个字符
void PSendChar(unsigned char inch)
{
ACC=inch;

F_TM=0;
BT_SND=0; //start bit
TIMER0_ENABLE; //启动
while(!F_TM);

BT_SND=ACC0; //先送出低位
F_TM=0;
while(!F_TM);

BT_SND=ACC1;
F_TM=0;
while(!F_TM);

BT_SND=ACC2;
F_TM=0;
while(!F_TM);

BT_SND=ACC3;
F_TM=0;
while(!F_TM);

BT_SND=ACC4;
F_TM=0;
while(!F_TM);

BT_SND=ACC5;
F_TM=0;
while(!F_TM);

BT_SND=ACC6;
F_TM=0;
while(!F_TM);

BT_SND=ACC7;
F_TM=0;
while(!F_TM);


BT_SND=1;
F_TM=0;
while(!F_TM);


TIMER0_DISABLE; //停止timer


}

//接收一个字符
unsigned char PGetChar()
{
TIMER0_ENABLE;
F_TM=0;
while(!F_TM); //等过起始位
ACC0=BT_REC;

TL0=TH0;

F_TM=0;
while(!F_TM);
ACC1=BT_REC;

F_TM=0;
while(!F_TM);
ACC2=BT_REC;

F_TM=0;
while(!F_TM);
ACC3=BT_REC;

F_TM=0;
while(!F_TM);
ACC4=BT_REC;

F_TM=0;
while(!F_TM);
ACC5=BT_REC;

F_TM=0;
while(!F_TM);
ACC6=BT_REC;

F_TM=0;
while(!F_TM);
ACC7=BT_REC;


F_TM=0;

while(!F_TM)
{
if(BT_REC)
{
break;
}
}
TIMER0_DISABLE; //停止timer
return ACC;


}
//检查是不是有起始位
bit StartBitOn()
{
return(BT_REC==0);

}
void main()
{
unsigned char gch,i;

TMOD=0x22; /*定时器1为工作模式2(8位自动重装),0为模式2(8位自动重装) */

PCON=00;

TR0=0; //在发送或接收才开始使用
TF0=0;
TH0=(256-96); //9600bps 就是 1000000/9600=104.167微秒 执行的timer是104.167*11.0592/12= 96

//            

TL0=TH0;
ET0=1;
EA=1;
Delay400Ms(); //启动等待,等LCM讲入工作状态
   LCMInit(); //LCM初始化
   Delay5Ms(); //延时片刻(可不要)
   DisplayListChar(2, 0, qq);
//    DisplayListChar(0, 1, tel);
   // ReadDataLCM();//测试用句无意义
PSendChar(0x55);
PSendChar(0xaa);
PSendChar(0x00);
PSendChar(0xff);

while(1)
{


if(StartBitOn())
   {
   gch=PGetChar();
   PSendChar(gch);
   for(i=0;i<8;i++)
      DisplayOneChar(7-i,1, ((gch>>i)&0x01)+48);
  
    }
}
}


//写数据
void WriteDataLCM(unsigned char WDLCM)
{
ReadStatusLCM(); //检测忙
LCM_Data = WDLCM;
LCM_RS = 1;
LCM_RW = 0;
LCM_E = 0; //若晶振速度太高可以在这后加小的延时
LCM_E = 0; //延时
LCM_E = 1;
}

//写指令
void WriteCommandLCM(unsigned char WCLCM,BuysC) //BuysC为0时忽略忙检测
{
if (BuysC) ReadStatusLCM(); //根据需要检测忙
LCM_Data = WCLCM;
LCM_RS = 0;
LCM_RW = 0;
LCM_E = 0;
LCM_E = 0;
LCM_E = 1;
}

/*/读数据
unsigned char ReadDataLCM(void)
{
LCM_RS = 1;
LCM_RW = 1;
LCM_E = 0;
LCM_E = 0;
LCM_E = 1;
return(LCM_Data);
}
*/
//读状态
unsigned char ReadStatusLCM(void)
{
LCM_Data = 0xFF;
LCM_RS = 0;
LCM_RW = 1;
LCM_E = 0;
LCM_E = 0;
LCM_E = 1;
while (LCM_Data & Busy); //检测忙信号
return(LCM_Data);
}

void LCMInit(void) //LCM初始化
{
LCM_Data = 0;
WriteCommandLCM(0x38,0); //三次显示模式设置,不检测忙信号
Delay5Ms();
WriteCommandLCM(0x38,0);
Delay5Ms();
WriteCommandLCM(0x38,0);
Delay5Ms();

WriteCommandLCM(0x38,1); //显示模式设置,开始要求每次检测忙信号
WriteCommandLCM(0x08,1); //关闭显示
WriteCommandLCM(0x01,1); //显示清屏
WriteCommandLCM(0x06,1); // 显示光标移动设置
WriteCommandLCM(0x0C,1); // 显示开及光标设置
}

//按指定位置显示一个字符
void DisplayOneChar(unsigned char X, unsigned char Y, unsigned char DData)
{
Y &= 0x1;
X &= 0xF; //限制X不能大于15,Y不能大于1
if (Y) X |= 0x40; //当要显示第二行时地址码+0x40;
X |= 0x80; //算出指令码
WriteCommandLCM(X, 0); //这里不检测忙信号,发送地址码
WriteDataLCM(DData);
}

//按指定位置显示一串字符
void DisplayListChar(unsigned char X, unsigned char Y, unsigned char code *DData)
{
unsigned char ListLength;

ListLength = 0;
Y &= 0x1;
X &= 0xF; //限制X不能大于15,Y不能大于1
while (DData[ListLength]>0x20) //若到达字串尾则退出
{
if (X <= 0xF) //X坐标应小于0xF
{
DisplayOneChar(X, Y, DData[ListLength]); //显示单个字符
ListLength++;
X++;
}
}
}

//5ms延时
void Delay5Ms(void)
{
unsigned int TempCyc = 5552;
while(TempCyc--);
}

//400ms延时
void Delay400Ms(void)
{
unsigned char TempCycA = 5;
unsigned int TempCycB;
while(TempCycA--)
{
TempCycB=7269;
while(TempCycB--);
};
}

关键字:51单片机  IO口  模拟串口 引用地址:利用51单片机实现IO口模拟串口

上一篇:KEIL中的ISD51仿真软件详细使用说明
下一篇:单片机利用在微型打印机中的应用设计

推荐阅读最新更新时间:2024-03-16 15:50

8051单片机基础1:8051的起源
作为电子工程师,有没有思考过这3个问题呢 为什么叫8051单片机呢? 8051单片机和MCS-51单片机有什么关系? 8051单片机还有市场空间吗? 单片机是单片微型计算机的简称,又称微控制器(Micro Control Unit,MCU)。 通常所说的8051单片机,属于MCS-51单片机的一种,MCS-51是Intel在1981年开发出来的。 Intel公司在1980年推出的MCS-51系列单片机奠定了单片微型计算机的经典体系结构,8位数据总线、16位地址总线、控制总线及方便扩展的外设接口。 MCS-51系列单片机包括:8031,8051,80C51,8751,8032,8052,8752等。 该系列单片机
[单片机]
80<font color='red'>51单片机</font>基础1:8051的起源
STC89C52之中断系统 ---- 51单片机的核心 自学笔记
一、中断系统 1.1、概念 cpu在处理某一事件A时,发生了另外一事件B请求cpu迅速去处理(中断发生); cup暂时中断当前的工作,转去处理事件B(中断响应和中断服务); 待cup将事件B处理完毕后,再回到原来事件A被中断的地方继续处理事件A(中断返回); 这一过程称为中断。 引起CPU中断的根源,称为中断源。中断源向CPU提出的中断请求。cup暂时中断原来的事务A,转去处理事件B。对事件B 处理完毕后,再回到原来被中断的地方(即:断点)称为中断返回,实现上述中断功能的部件称为中断系统。 1.2、中断系统的功能与优点 解决了快速主机与慢速i/o设备的数据传送问题。 分时操作:cpu可以为多个io设备服务,
[单片机]
STC89C52之中断系统 ---- <font color='red'>51单片机</font>的核心 自学笔记
51单片机中的ROM和RAM分别是什么?
众所周知,51 内部的存储器分为数据存储器 RAM 和程序存储器 ROM。以 AT89c51 为例,其中有 128 字节随机存储器(又称数据储存器 RAM)和 4K 字节的只读存 储器(又称程序存储器 ROM)。 先说说这个 4K 字节的程序存储器或者说只读存储器,我们写的程序经过编译器 编译成机器码都是存在这个区域,所以称为程序存储器;但单片机上电执行的时 候,此区域内的数据只能读取而不能写入,他的只读存储器的名称从这而来。 89c51 的 ROM 采用的是 FPEROM(Flash Programmable and Erasable Read Only Memory),具体工艺我也不太清楚,号称可以擦写 1000 次
[单片机]
手把手教学51单片机 | 第五课 独立键盘 矩阵键盘
编码键盘 电脑的键盘 非编码键盘 (1)硬件消抖 (2)软件消抖 独立键盘 线与的关系 先给IO口高电平 用一个if检测IO口高低电平,若按键按下IO口为0(1&0=0)没按下则继续保持高电平 按键在闭合和断开开始 触电会存在抖动的现象 2.矩阵键盘 #include reg52.h #define uint unsigned int #define uchar unsigned char sbit dula=P2^6; sbit wela=P2^7; sbit key1=P3^4; uchar code table ={ 0x3f,0x06,0x5b,0x4f, 0x66,0x6d,0x7d,0x07, 0x7
[单片机]
手把手教学<font color='red'>51单片机</font> | 第五课 独立键盘 矩阵键盘
51单片机定时器和计数器
8051单片机内部有两个定时/计数器T0及T1,具有定时和计数两种功能。T0及T1在计数过程中不需要CPU参与,也不影响CPU的其他工作。当计数溢出后,定时/计数器给出中断信号,申请CPU停止当前的工作,去处理预先设定的中断事件。 一、T1内部结构 定时器工作模式:对内部时钟信号计数。由于时钟频率是定值,所以可根据计数值计算出定时时间。 计数器工作模式:是对加在T1(P3.5)引脚上的外部脉冲进行计数。 二、计数功能 计数器用于统计从TO(P3.4)和Tl(P3.5)两个引脚输入脉冲的负跳变数量。负跳变是指前一个机器周期采样为高电平,后一个机器周期为低电平。每输入一个脉冲负跳变,计数器加1。 输入脉冲的高电平与低电平至少应保持
[单片机]
<font color='red'>51单片机</font>定时器和计数器
基于51单片机的大功率直流有刷电机的PWM调速控制
本人最近一直想用51单片机来设计制作一个 大功率直流有刷电机PWM调速控制器 。由于平时工作忙,没时间。所以,这个东东花了我很长时间。每天晚上下了班,回家就弄,一直搞到十一二点钟才休息。期间,也花了我不少钱,也失败了N次。终于,功夫不负有心人,我终于成功了,哈哈~~。 由于这个是大功率的直流有刷电机PWM调速控制器,所以就不能用晶体管来驱动了,必须用MOS管来驱动。MOS管不仅驱动能力强,而且效率高。为了提高系统的稳定性,可靠性,适用范围广等特点,本系统,采用双电源供电。控制电路一组电源,电压分别为5V和15V。功率输出部分一组电源,以适应不同电压的电动机。至于功率,可以根据实际情况,通过并联MOS管来决绝,但同时也要修改下驱动
[单片机]
基于<font color='red'>51单片机</font>的大功率直流有刷电机的PWM调速控制
51单片机程序——定时器控制LED闪烁
#include reg52.h #define uint unsigned int uint i=0; void delay(uint z) //延迟函数 { uint x,y; for(x=z;x 0;x--) for(y=20;y 0;y--); } void main (void) { TMOD=0x10; //TMOD赋值,以确定T0和T1的工作方式 TH1=(65536-50000)/256; //计算初值,并将其写入TH0、TL0或TH1、TL1 TL1=(65536-50000)%6; EA=1; //打开总中
[单片机]
51单片机定时中断实现显示的程序
第一位始终显示0,第二位显示在0-9之间循环 ;************************************************** Counter EQU 59H ;计数器,显示程序通过它得知现正显示哪个 数码管 FIRST EQU P2.7 ;第一位数码管的位控制 SECOND EQU P2.6 ;第二位数码管的位控制 DISPBUF EQU 5AH ;显示缓冲区为5AH和5BH ORG 0000H AJMP START ORG 000BH ;定时器T0的入口 AJMP DISP ;显示程序 ORG 30H START: MOV SP,#5FH ;设置堆栈 MOV P1,#0FFH MOV P0,#0FFH
[单片机]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved