打印

GPIO 模拟串口

[复制链接]
3098|14
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
victor3l|  楼主 | 2015-11-2 18:12 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
大家好,
我现在要实现一个功能,检测CC2540的外部32KHz的晶振有没有起振。 如果没有起振,我要通过一个GPIO把它模拟成串口,给主MCU发送一些数据,告诉主MCU,这个情况。 我使用的串口波特率是115200bps, 1位停止位,8位数据位,没有校验位。那么每一位所占的时间就是1000000/115200 = 8.7us. 我的程序这样写:
void SimuUart_115200(unsigned char data)
{
        char i = 8;
        unsigned char temp = 0;

        P0_1 = 0; //起始位

        SysCtlDelay(480);

       

        while(i--)
        {
                temp = data;
                temp &= 0x01;

      //发送1位数据
                if(temp == 1)
                {
                        P0_1 = 1;
                }
                else
                {
                        P0_1 = 0;
                }

                SysCtlDelay(480);

                data = data >> 1;
        }

        P0_1 = 1; //结束位

        SysCtlDelay(480);

}
可是我用串口助手接收时,我随便发送一些字节,串口助手收到的是错的。这里的延时,我用示波器测量过, SysCtlDelay(480) 约 8.7us. 请问哪里有错误?

相关帖子

沙发
ningling_21| | 2015-11-2 18:27 | 只看该作者
改用9600波特率试试呢

使用特权

评论回复
板凳
ayb_ice| | 2015-11-2 18:45 | 只看该作者
发送期间关掉中断,避免影响,另外延时要很准

使用特权

评论回复
地板
457344370| | 2015-11-3 07:00 | 只看该作者
用逻辑分析仪抓以下就知道什么原因了,内部晶振还是用9600以下的波特率吧,如果内部晶振误差大,建议加跟时钟线做通讯

使用特权

评论回复
5
victor3l|  楼主 | 2015-11-3 08:04 | 只看该作者
ayb_ice 发表于 2015-11-2 18:45
发送期间关掉中断,避免影响,另外延时要很准

实际上,这里我仅仅是在测试,在整个工程的最前面,使用了while(1)括住上面这个函数,在主mcu与cc2540没有通讯的前提下,应该不会有中断吧。

使用特权

评论回复
6
ayb_ice| | 2015-11-3 08:15 | 只看该作者
victor3l 发表于 2015-11-3 08:04
实际上,这里我仅仅是在测试,在整个工程的最前面,使用了while(1)括住上面这个函数,在主mcu与cc2540 ...

如果是CC2540模拟UART发数据给MCU的话

CC2540应该是跑什么协议栈吧,那肯定有中断的,而且不少

使用特权

评论回复
7
无量寿经| | 2015-11-3 21:51 | 只看该作者
以下内容来源于《51单片机轻松入门——基于STC15W4K系列》
例4.8  任意IO口模拟串口,22.1184MHz内部R/C时钟,波特率115200bps,每bit 位传送时间按通信速率115200 bit /s计算为1/115200=8.68μS。
#include"STC15W4K.H"           // 包含"STC15W4K.H"寄存器定义头文件  
#define RECEIVE_MAX_BYTES  1    //最大接收字节数
unsigned charRecvBuf[16];      // 接收数据缓冲区
unsigned charRecvCount=0;      // 接收数据计数器
sbit T_TXD=P3^2;                // 发送数据的引脚   
sbit R_RXD=P3^3;                // 接收数据的引脚
unsigned char bdata dat;        // dat是可位寻址的变量
sbit dat7=dat^7;sbitdat6=dat^6;sbit dat5=dat^5;sbit dat4=dat^4;
sbit dat3=dat^3;sbitdat2=dat^2;sbit dat1=dat^1;sbit dat0=dat^0;  // 取出dat的各个位
void delay8_6uS()              // 8.6uS延时函数
{
    unsigned char t=46;
    while(--t);
}
void delay2_6uS()      // 理论计算值4.3uS实际出现数据出错现象,根据调试结果确定为2.6uS
{
    unsignedchar t=12;
    while(--t);
}
void SendByte(unsigned charDat)
{
    dat= Dat;
    T_TXD=0; delay8_6uS();                  // 发送起始位
    T_TXD=dat0; delay8_6uS();               //数据最低位
    T_TXD=dat1; delay8_6uS();
    T_TXD=dat2; delay8_6uS();
    T_TXD=dat3; delay8_6uS();
    T_TXD=dat4; delay8_6uS();
    T_TXD=dat5; delay8_6uS();
    T_TXD=dat6; delay8_6uS();
    T_TXD=dat7; delay8_6uS();               // 数据最高位   
    T_TXD=1; delay8_6uS();                 // 发送停止位              
}
unsigned char RecvByte()
{
    unsigned char RXD_OK=0;                  // 数据接收完成标志
    delay2_6uS();                            // 起始位中心位置
    if(R_RXD==0)                             // 确认起始位正常
    {
        delay8_6uS();dat0=R_RXD;             // 数据最低位,数据位中心位置读数据
        delay8_6uS();dat1=R_RXD;
        delay8_6uS();dat2=R_RXD;   
        delay8_6uS();dat3=R_RXD;   
        delay8_6uS();dat4=R_RXD;
        delay8_6uS();dat5=R_RXD;
        delay8_6uS();dat6=R_RXD;
        delay8_6uS();dat7=R_RXD;              // 数据最高位
        delay8_6uS();                         // 停止位
        if(R_RXD==1)                          // 确认停止位正常
        {
            RXD_OK=1;
        }     
    }  
    return  RXD_OK;
}
void PrintfStr(char * pstr)                   // 串口打印字符串
{
    while(*pstr)   
    {
        SendByte(*pstr++);
    }
}
void main(void)
{  
    unsigned char i;   
    PrintfStr("模拟串口:STC15\r\n");
    while(1)               
    {
        if(R_RXD==0)    // 死循环不断检测R_RXD是否有起始位出现
        {
            if (RecvByte()!=0)                     // 一个字节接收正常
            {      
                RecvBuf[RecvCount++]=dat;   
                if(RecvCount>=RECEIVE_MAX_BYTES)
                {
                    RecvCount=0;
                    for(i=0;i<RECEIVE_MAX_BYTES;i++)
                    {
                        SendByte(RecvBuf+1);    // 接收到得数据+1后发回
                    }
                }
            }
        }
    }
}

使用特权

评论回复
8
zhaoyu2005| | 2015-11-4 08:51 | 只看该作者
模拟串口,还整这么高波特率,有自虐倾向

使用特权

评论回复
9
victor3l|  楼主 | 2015-11-6 16:59 | 只看该作者
ningling_21 发表于 2015-11-2 18:27
改用9600波特率试试呢

是的,9600可以的。115200不行,后面改用别的办法来解决问题,不模拟串口了。

使用特权

评论回复
10
jinwandalaohu| | 2015-11-11 20:34 | 只看该作者
用定时器中断来做波特率,软件延时不准

使用特权

评论回复
11
JerryWu75| | 2015-11-12 08:49 | 只看该作者
本帖最后由 JerryWu75 于 2015-11-12 08:57 编辑

可以考虑用PWM调制的方法,例如:
1, 不发送数据时,电平为高;
2, 首先发送引导码, 一个2ms的50%占空比信号,先发低电平;
3, 发送数据, 数据1是一个500us的50%占空比信号,数据0是一个1ms的50%占空比信号, 先发低电平;
4, 发送结束位,一个8ms的50%占空比的信号,先发低电平;
5, 发送结束,置高电平.
校验和用软件做, 这个是家电上遥控器发送控制码的逻辑.
我用CC2541做过类似的功能,用T1和T3做调制,通过P0_3发送数据,另外一端用NEC 9234通过GPIO中断+定时器捕捉接收数据,然后通过UART发送到计算机.

使用特权

评论回复
12
布丁奶茶| | 2015-12-18 15:42 | 只看该作者
楼主,我也在研究模拟串口的问题,现在是一头雾水,请问你的模拟串口是如何实现发送和接收的?又是如何仿真的?请指教!

使用特权

评论回复
13
NE5532| | 2015-12-19 16:33 | 只看该作者
串口,就是一堆高低电平的组合,模拟串口,就是用IO口实现这堆高低电平就是了啊,还雾水么?

使用特权

评论回复
14
MOn51| | 2015-12-24 13:57 | 只看该作者
我原来发过例程,用RC震荡。

使用特权

评论回复
15
Tiger535| | 2017-4-22 19:15 | 只看该作者
学习中

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

77

主题

308

帖子

5

粉丝