打印
[AVR单片机]

典型的单片机串口程序,你读得懂吗,有问题?

[复制链接]
2842|10
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
uuuren|  楼主 | 2010-11-25 17:28 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 uuuren 于 2010-11-25 17:35 编辑

/*** Initialization of Serial Port(Ex.Baud Rate setting) ***/
void InitSerial(void)
{SCON = 0x50; // SERIAL MODE 1, SM00 = 0, SM01 =1, REN=1
TMOD |= 0x20; // Timer1 MODE 2
PCON |= 0x80; // SMOD0 = 1
TL1 = 0xFC;  // Baud Rate Setting to 115200bps
TH1 = 0xFC;  // Baud Rate Setting to 115200bps
TR1 = 1;  // Timer1 START
    txbufrflag = 1;
RI = 0;
TI = 0;
txdptro = 0;
txdptri = 0;
rxdptro = 0;
rxdptri = 0;
ES = 1;  //  1}


void PU_INT4(void) interrupt 4 //中断
{  EA = 0;     
     if (RI)
        {  RI = 0;
          uartrxd[rxdptri++] = SBUF; }
     if (TI)
     { TI = 0;
        if (txdptro == txdptri)
             txbufrflag = 1;
         else
             SBUF = uarttxd[txdptro++];
     }
     EA = 1;
}

char putchar(char  accum)  // 串行口输出
{  while (((txdptri+1) & 0x0f) == txdptro);
    uarttxd[txdptri++]=accum;
    if (txbufrflag)
       {txbufrflag = 0;
       TI = 1;}
    return accum;}

unsigned char GetcomLn(unsigned char *temp)
{unsigned char byData,count;
  count = 0;
while(rxdptro != rxdptri)
  {temp[count++]  = uartrxd[rxdptro++];
    for(byData = 0; byData < 30; byData++)
       {if (rxdptri == rxdptro)  wait_1us(5);
          else  break;}
   }
temp[count] = 0;  //字符串最后加一空格
return count;
}

请教问题:putchar(char accum)while (((txdptri+1) & 0x0f) == txdptro);有什么作用?
      以及GetcomLn中那个for循环有什么用?

相关帖子

沙发
airwill| | 2010-11-28 22:22 | 只看该作者
putchar(char accum)中 while (((txdptri+1) & 0x0f) == txdptro);有什么作用?
没有看到 uarttxd 的定义, 我估计是 16 Bytes 的数组吧, ((txdptri+1) & 0x0f) 目的是检测是否存满了数据了.    & 0x0f  可以提高软件健壮性.
  GetcomLn 中那个 for 循环有什么用?
  这是个延时, 等待数据接收.

使用特权

评论回复
板凳
mxh0506| | 2010-12-1 12:37 | 只看该作者
本帖最后由 mxh0506 于 2010-12-1 12:39 编辑

程序的整体架构还行,用中断方式+缓冲区进行收发可以提高执行效率。
但是后面两个函数就不敢恭维了:都出现了用循环等待的方式,纯粹浪费CPU处理时间。尤其是while (((txdptri+1) & 0x0f) == txdptro);这一句(应该是判断环形缓冲区满吧?),如果条件不满足,就成了死循环。
另外,对于中断里用到的变量,在其它位置调用,应该加上适当的保护措施。

使用特权

评论回复
地板
mohanwei| | 2010-12-1 12:50 | 只看该作者
格式化一下,看看是不是养眼多了:

/*** Initialization of Serial Port(Ex.Baud Rate setting) ***/
void InitSerial(void)
{
        SCON = 0x50; // SERIAL MODE 1, SM00 = 0, SM01 =1, REN=1
        TMOD |= 0x20; // Timer1 MODE 2
        PCON |= 0x80; // SMOD0 = 1
        TL1 = 0xFC; // Baud Rate Setting to 115200bps
        TH1 = 0xFC; // Baud Rate Setting to 115200bps
        TR1 = 1; // Timer1 START
        txbufrflag = 1;
        RI = 0;
        TI = 0;
        txdptro = 0;
        txdptri = 0;
        rxdptro = 0;
        rxdptri = 0;
        ES = 1; //  1
}

void PU_INT4(void)interrupt 4  //中断
{
        EA = 0;
        if (RI)
        {
                RI = 0;
                uartrxd[rxdptri++] = SBUF;
        }
        if (TI)
        {
                TI = 0;
                if (txdptro == txdptri)
                        txbufrflag = 1;
                else
                        SBUF = uarttxd[txdptro++];
        }
        EA = 1;
}

char putchar(char accum) // 串行口输出
{
        while (((txdptri + 1) &0x0f) == txdptro)
                ;
        uarttxd[txdptri++] = accum;
        if (txbufrflag)
        {
                txbufrflag = 0;
                TI = 1;
        }
        return accum;
}

unsigned char GetcomLn(unsigned char *temp)
{
        unsigned char byData, count;
        count = 0;
        while (rxdptro != rxdptri)
        {
                temp[count++] = uartrxd[rxdptro++];
                for (byData = 0; byData < 30; byData++)
                {
                        if (rxdptri == rxdptro)
                                wait_1us(5);
                        else
                                break;
                }
        }
        temp[count] = 0; //字符串最后加一空格
        return count;
}

使用特权

评论回复
5
dong_abc| | 2010-12-5 02:18 | 只看该作者
是养眼多了

使用特权

评论回复
6
疯子8972| | 2010-12-7 21:19 | 只看该作者
BUG

使用特权

评论回复
7
疯子8972| | 2010-12-7 21:33 | 只看该作者
这样的程序铺天盖地   网上到处都是
让初学者学习一下还可以
作为产品中的代码要害死人的
代码中有隐形BUG
并且没有移植性,若编译器的优化等级高,很可能会有错误

使用特权

评论回复
8
laurel25_604| | 2011-3-6 23:33 | 只看该作者
初学者看不懂

使用特权

评论回复
9
joyme| | 2011-3-8 12:51 | 只看该作者
uarttxd[] uartrxd[]分别是发送和接受缓冲区,大小为16字节都可以
rxdptri,  rxdptro分别为写入和读出指针,当读出指针等于写入指针说明写满
同样txdprti,txdptro为发送缓冲区的写入和读出指针,当读出指针等于写入指针说明发送完毕

当缓冲区为16字节时,写入指针&0f可以避免数组超界

使用特权

评论回复
10
sdpz| | 2011-3-10 17:09 | 只看该作者
QueuePutByte   往队列加入字节的宏
QueueDataCount  获得队列内元素个数的宏
QueueGetByte  从队列取字节的宏

void UartISR() interrupt 4 using 3
{
        unsigned char buf;

        if (RI)
        {
                RI = 0;
                buf = SBUF;
                QueuePutByte(&rx_queue, buf);
        }
        else if (TI)
        {
                TI = 0;
               
                if (QueueDataCount(&tx_queue) > 0)
                {
                        QueueGetByte(&tx_queue, &buf);
                        SBUF = buf;
                }
        }
}

使用特权

评论回复
11
Step1toStep5| | 2011-3-22 12:02 | 只看该作者
来点浅显易懂的解释?

使用特权

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

本版积分规则

44

主题

74

帖子

0

粉丝