芯源半导体CW32
直播中

张桂兰

8年用户 1399经验值
私信 关注
[经验]

普通IO口模拟串口的功能

要模拟串口首先要清楚串口数据传输过程中的原理。


所以最简单的串口传输一个字节总共有10个电平变化,每个电平的宽度由波特率决定的。


下面看一个通过波特率如何计算每个位的电平宽度。


可以计算出传输1位所需要的时间 T1 = 1/9600 约为104us。


上图中就是一个字节的完整波形,起始位为低电平,结束位为高电平,中间8位为数据位,无校验位。数据位是低位在前,高位在后。也就是和起始位挨着的是最低位,和结束位挨着的是最高位。通过这个波形就可以分析出,发送的数据是0x00。


起始位为低电平,结束位为高电平,中间数据位有一个高电平,其余都是低电平,按照低位在前,高位在后规律,数据位就是0000 0001 刚好是16进制的0x01。


//输出1

{

}

void Send_0( void )

    SIM_TXD = 0;

//发送一个字节

{

    unsigned char i;

    //发送起始位

    delay_us( 100 );

    for( i = 0; i < 8; i++ )

        value = ( sdata   0x01 ); //先传低位

        {

        }

        {

        }

        sdata = sdata >> 1;

    //停止位

    delay_us( 100 );           

首先发送起始位,将IO口电平拉低,延时104us,下来发送8位数据位,低位在前,高位在后,每发送一位就延时104us。最后发送结束位,将IO口电平置高,在延时104us。这样一个字节就发送结束了。


下面再看接收程序


void ReadByte( void )

    unsigned char i, value = 0;

    {

        delay_us( 100 );

        for( i = 0; i < 8; i++ )

            value >>= 1;

            {

            }

        }

        //delay_us(100);  //一次性接收大量数据时,防止程序执行代码时浪费时间,在结束符时可以不用等待

        RecBuf = value;

    }

接收数据就更好理解了,读取IO口的电平,如果出现低电平就开始接收数据,然后读取8个数据位的电平,在等待结束位结束。这样一个字节的数据就接收完成了。


有两种方式去实现,一种是在死循环中用查询方式去判断,一直读取IO的的电平,如果出现低电平就认为串口有数据发送进来了。


//查询方式接收数据

{

    unsigned char recstr[100] = {0};

    while( 1 )

        if( !RecFlag )            //未收到数据时扫描

            ReadByte();          //扫描数据

        }

        {

            RecFlag = 0;

            RecBuf = 0;

        }

        {

            WriteString( recstr );  //发送接收到的数据

            i = 0;                  //清除接收数据数组下标

            {

            }

        }

        {

            return;

    }

这种方式实现起来比较简单,但是对于程序编写比较麻烦,因为要一直监视者IO口,所以程序干其他事情时,很有可能错过数据的接收。可以用第二种方式,IO口中断来判断什么时候要开始接收数据,将IO口设置为下降沿中断,当有下降沿出现时,说明串口有数据进来了,然后再去读取串口数据。没有中断发生时,程序就可以干其他事情了。


//通道PC3口的下降沿中断检测数据

#pragma vector = 7                  // IAR中的中断号,要在STVD中的中断号上加2

{

    ReadByte();

    {

        {

            recCNT = 0;

    }

    {

        {

            RecBuf = 0;

        else if( RecBuf == 0x0d )   //收到0x0d 标记结束符开始

            recEnd |= 0x01;

    }

}


当出现下降沿之后进入中断程序,这时候要关闭外部中断,开始读取IO口电平状态。若不关闭中断,在读取IO电平的过程中中断还会不停的进入,这样就会影响读取数据的准确性。所以进入中断会首先要关闭中断,接收完一个字节之后,在打开中断,接收下一个字节。直到收到了回车换行符(也就是0x0D 0x0A),就认为数据发送已经结束。就退出接收过程,然后主程序就可以去处理接收到的数据了。


更多回帖

发帖
×
20
完善资料,
赚取积分