IO口模拟USART 通信

发布者:JoyfulJourney最新更新时间:2016-11-04 来源: eefocus关键字:IO口  模拟USART  通信 手机看文章 扫描二维码
随时随地手机看文章
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);
        }
    }
}
关键字:IO口  模拟USART  通信 引用地址:IO口模拟USART 通信

上一篇:经典的按键处理程序
下一篇:流量监控系统信号测量电子电路

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

STM32单片机GPIO口的工作模式解析
STM32单片机的每组IO口都有4个32位配置寄存器用于配置GPIOx_MODER, GPIOx_OTYPER, GPIOx_OSPEEDR和GPIOx_PUPDR,2个32位数据寄存器用于配置输入和输出寄存器GPIOx_IDR和GPIOx_ODR,1个32位置位复位寄存器GPIOx_BSRR,1个32位锁定寄存器GPIOx_LCKR和2个32位复用功能选择寄存器GPIOx_AFRH和GPIOx_AFRL。 GPIO的输出状态可以配置为推挽或开漏加上上拉或下拉。输出数据既可以来自输出数据寄存器,也可以由其他外围寄存器发出。每组IO口的速度都是可以配置的,可以配置为25MHz,50MHz或是100Mhz。数据输入同样也有几种模式
[单片机]
STM32单片机GP<font color='red'>IO口</font>的工作模式解析
通信、计量、主控三芯一体,芯象半导体全新NB-IoT芯片问市
2020年,NB-IoT部署应用加速发展,NB-IoT技术获得越来越多的行业认可,芯象半导体依托自身长期技术积累和大规模SOC芯片设计的成功经验,基于对行业客户实际需求和物联网芯片所面临挑战的理解,推出一款创新产品,旨在解决行业客户普遍关注的几类问题。在MCU产品交货期拖长、价格上涨的市场环境下,芯象半导体LH3200内置独立开放Open CPU在试商用中完全替代了原有物联网方案的外置MCU,帮助客户降低成本、提升效率,同时也证明:NB-IoT SoC芯片内置独立Open CPU可以替代物联网终端设计中的MCU。 谈到NB-IoT,从标准到芯片以及模组,再到设备、网络、平台以及行业解决方案,NB-IoT技术都是由中国产业链主导
[物联网]
<font color='red'>通信</font>、计量、主控三芯一体,芯象半导体全新NB-IoT芯片问市
51单片机STC89C52点亮一个LED(IO口的位操作)
程序源码 /*-----------------------包含头文件区域-------------------------*/ #include reg52.h //单片机头文件 /*-----------------------端口/引脚定义区域----------------------*/ sbit LED=P2^0; //位定义P2.0引脚名为LED /*-----------------------主函数区域-----------------------------*/ void main() { LED=0; //LED端口输出低电平,即点亮LED, while(1); //死循
[单片机]
51单片机STC89C52点亮一个LED(<font color='red'>IO口</font>的位操作)
主流新兴通信接口原理分析
  如果查看一下典型通信系统的结构,可以看出很多元件都需要相互进行通信。为满足数据通道中各种元件的不同需求,因而出现了各种不同的接口标准。要了解各种接口的优缺点,就需要查看元件本身及每个元件所发生的通信类型。这里将从光电接口开始,然后逐一介绍内部元件,直至交换架构(switch fabric)。 a.与串并行转换器相连的光电器件    在高速光纤通信系统中,传输的数据流需要进行格式转换,即在光纤传输时的串行格式及在电子处理时的并行格式之间转换。串化器-解串器 (一般被称作串并行转换器) 就是用来实现这种转换的。串并行转换器与光电传感器间的接口通常为高速串行数据流,利用一种编码方案实现不同信令,这样可从数据恢复嵌入的时钟。视
[嵌入式]
stm32---CAN通信
can.c #include can.h /************************************************************* 函数名:CAN_Mode_Init(u8 tsjw,u8 tbs2,u8 tbs1,u16 brp,u8 mode) 功能:CAN初始化 变量: //tsjw:重新同步跳跃时间单元.范围:CAN_SJW_1tq~ CAN_SJW_4tq //tbs2:时间段2的时间单元. 范围:CAN_BS2_1tq~CAN_BS2_8tq; //tbs1:时间段1的时间单元. 范围:CAN_BS1_1tq ~CAN_BS1_16tq //brp :波特率分频器.范围:
[单片机]
恩智浦最新CAN收发器系列保障CAN通信安全而无需加密
1 月 31 日 - 恩智浦半导体NXP Semiconductors(纳斯达克代码:NXPI),全球最大的汽车半导体解决方案供应商1 ,今日宣布推出新的安全型CAN收发器系列,该系列为安全型CAN通信提供无缝、高效的解决方案,且无需软件或加密。 每辆汽车中都使用CAN网络来连接电子控制单元(ECU),预计未来十年它仍会是主导性网络。随着汽车电子设备不断增多,跨CAN网络交换的实时数据量也在增加。 CAN是一个强大的多点连接网络,迄今为止,车内大部分数据通信都没有安全措施,单个受到破坏的ECU可以直接访问联网的ECU。目前市场上的安全解决方案 使用基于加密和复杂密钥管理的报文认证码(MAC)来保护CAN通信, 但这势必造成CA
[汽车电子]
联邦通信委员会主席明确反对AT&T收购T-Mobile
据国外媒体报道,美国联邦 通信 委员会主席朱利叶斯·格纳考斯基(Julius Genachowski)在周二下发给其他委员会成员的一份文件中明确反对手机巨头AT&T与T-Mobile美国公司的合并,部分业内人士曾表示此举将为急需改善的农村地区的无限服务带来福音。 格纳考斯基建议将AT&T公司这笔价值390亿美元的收购案交由行政法官进行审查和听证。这是联邦通信委员会在反对一项合并案时的惯常做法。 华盛顿州圣海伦(St.Helena)众议员麦克·汤普森(MikeThompson)曾于7月发表声明,支持这一合并案。他在一封信中表示,这一交易将改善农村地区的电信服务。 汤普森在信中指出:“为了维持我国长期的经济增长,
[网络通信]
车载通信发展史:从传统车载网络到车载以太网
前言 在汽车智能化、网联化的大背景下,ADAS技术的不断革新、车载多媒体持续推进、各种智能化功能的推陈出新以及大数据、云计算等一系列技术的发展,极大推进了车载网络容量需求的爆发式发展。CAN或FlexRay等传统车载网络已经逐渐无法满足新需求,车载以太网应运而生。 1 传统车载网络介绍 当前主流的传统车载网络主要包括CAN、LIN、FlexRay和MOST。 CAN: Controller Area Network 一种用于实时应用的串行通讯协议总线,它可以使用双绞线来传输信号,是世界上应用最广泛的现场总线之一。CAN协议用于汽车中各种不同元件之间的通信,以此取代昂贵而笨重的
[汽车电子]
车载<font color='red'>通信</font>发展史:从传统车载网络到车载以太网
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

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

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

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