打印

PK 使人进步:晒晒你的串口程序

[复制链接]
楼主: 西安农民工
手机看帖
扫描二维码
随时随地手机跟帖
21
Periodic| | 2011-11-11 19:54 | 只看该作者 回帖奖励 |倒序浏览
MARK

使用特权

评论回复
22
程序匠人| | 2011-11-11 20:10 | 只看该作者
哈哈,又见pk

使用特权

评论回复
23
haitao10086| | 2011-11-11 22:52 | 只看该作者
不错

使用特权

评论回复
24
lgnativs| | 2011-11-12 09:40 | 只看该作者
#include "hal_uart.h"

static uint uart_rx_cnt = 0;
static uint uart_tx_cnt = 0;
uint uart_rx_len;
uint uart_tx_len;
byte * uart_rx_ptr;
byte * uart_tx_ptr;
byte uart_rx_completed;
byte uart_tx_completed;

CALLBACKFUNC pHandleReceive;

static void uart0_isr(void) interrupt
INTERRUPT_UART0
{
  if(RI0 == 1)
  {
    RI0 = 0;
    if (uart_rx_cnt < uart_rx_len)
    {
      *(uart_rx_ptr + uart_rx_cnt) = SBUF0;
      uart_rx_cnt++;
      if(uart_rx_cnt ==
uart_rx_len)

uart_rx_completed = 1;
    }
    if(pHandleReceive != 0)
    {

(*pHandleReceive)(SBUF0);
    }
  }
  if(TI0 == 1)
  {
    TI0 = 0;

uart_tx_cnt++;

if(uart_tx_cnt >= uart_tx_len)

uart_tx_completed = 1;

else
    {
      SBUF0 = *(uart_tx_ptr + uart_tx_cnt);
    }
  }
}


void hal_uart_init(BAUD_RATE baud)
{

XBR0 |= 0x01;
//UART0 Tx-P0.4,Rx-P0.5

P0MDOUT |= 0x10;
//Tx as Push-Pull

ES0 = 0;                      // Disable UART0 interrupt while initializing

uart_rx_len = 0;

uart_tx_len = 0;

uart_rx_completed = 0;

uart_tx_completed = 0;

pHandleReceive = 0;
  switch(baud)
  {
    case BAUD_9600:

    TMOD      = 0x20;
// 8位重装载模式

    CKCON     = 0x00;
// T1分频系数

    TH1       = 0x30;
// 定时器重装载值
      break;
    case BAUD_14400:

    TMOD      = 0x20;

    CKCON     = 0x00;

    TH1       = 0x75;


break;

case BAUD_19200:

    TMOD      = 0x20;

    CKCON     = 0x00;

    TH1       = 0x98;

break;

case BAUD_57600:

TMOD      = 0x20;

    CKCON     = 0x01;

    TH1       = 0x98;

break;

case BAUD_115200:

    TMOD      = 0x20;

    CKCON     = 0x08;

    TH1       = 0x30;


break;

    default:

    TMOD      = 0x20;

    CKCON     = 0x00;

    TH1       = 0x30;
      break;
  }

SCON0 = 0x10;
//8-bit uart;RI0 will only be activated if stop bit is logic level 1.

TR1 = 1;

ET1 = 0;

ES0 = 1;              // Enable UART0 interrupt
}

void hal_uart_tx(byte * pTxBuff,uint length)
{

uart_tx_ptr = pTxBuff;

uart_tx_len = length;

uart_tx_cnt = 0;

uart_tx_completed = 0;

SBUF0 = *uart_tx_ptr;


while(uart_tx_completed == 0);
}

void hal_uart_rx(byte * pRxBuff,uint length)
{

uart_rx_ptr = pRxBuff;

uart_rx_len = length;

uart_rx_cnt = 0;

uart_rx_completed = 0;

while(uart_rx_completed == 0);
}

void hal_uart_tx_overlapped(byte * pTxBuff,uint length)
{

uart_tx_ptr = pTxBuff;

uart_tx_len = length;

uart_tx_cnt = 0;

uart_tx_completed = 0;

SBUF0 = *uart_tx_ptr;

}

void hal_uart_rx_overlapped(byte * pRxBuff,uint length)
{

uart_rx_ptr = pRxBuff;

uart_rx_len = length;

uart_rx_cnt = 0;

uart_rx_completed = 0;
}
void hal_uart_tx_byte(byte txData)
{

hal_uart_tx(&txData,1);
}

byte hal_uart_rx_byte()
{

byte temp;

hal_uart_rx(&temp,1);

return temp;

}

byte hal_uart_rx_count()
{

return uart_rx_cnt;

}
bool hal_uart_tx_complete()
{

return uart_tx_completed;
}

bool hal_uart_rx_complete()
{

return uart_rx_completed;
}

void hal_uart_registe_RecieveEvent(CALLBACKFUNC receiveProc)
{

pHandleReceive = receiveProc;

}

使用特权

评论回复
评分
参与人数 1威望 +1 收起 理由
草履虫 + 1 这个思想比LZ的思想要好.中断里尽可能只做 ...
25
lgnativs| | 2011-11-12 09:44 | 只看该作者
我的通用串口程序.
主要功能:
1.能完成同步/异步的多字节发送接收;
2.接收消息回调函数;
第一次贴代码,格式有点乱请见谅.

使用特权

评论回复
26
hotpower| | 2011-11-12 12:20 | 只看该作者
不错,回调函数上档次。

使用特权

评论回复
27
ningling_21| | 2011-11-13 22:36 | 只看该作者

这回开眼界了...

使用特权

评论回复
28
sytu_chyq| | 2011-11-16 15:07 | 只看该作者
我中断程序没那么复杂
只管把数据放入缓存
然后一次性读出
再作判断

使用特权

评论回复
评论
阮天宇00 2012-12-17 13:07 回复TA
你是做arm的?BUFFER有那么大么?反正我都是接受一个处理一个,一般的数据处理还是不会出问题的。我一般给串口2个byte 
评分
参与人数 1威望 +1 收起 理由
shizaigaole + 1
29
lgnativs| | 2011-11-16 15:37 | 只看该作者
这个串口程序主要考虑到通用性,是想把它作为一个硬件抽象层来用的(hardware abstract layer).这样就不必每次重写串口程序了.

使用特权

评论回复
30
mugenwon| | 2011-11-16 16:07 | 只看该作者
本帖最后由 mugenwon 于 2011-11-16 16:12 编辑

哈,我也来一段AVR的吧。没有加入超时处理。因为信号有自动重启功能,在定时器里面也有状态超时切换功能。只帖发送和接收部分。因为某些保密原因状态机,还有程序有所删减。。。数据是不需要校验的,本来就不是数据包。不过在处理数据的地方可以自己加校验。

//接收发送DMX512信号,波特率250K
//**************************************************************
//UART接收中断
//**************************************************************
#pragma interrupt_handler uart0_rx_isr:14        
void uart0_rx_isr(void)
{        uchar sreg=SREG;        
        uchar kudr;
    static uint cc_indata_num;
    static d512_innum;
        
//================================
//接受512数据模式
//================================
if(UCSRA&0x10)        //帧错误,认为是大空挡
{        kudr=UDR;
        if((m_d512_r==M512_CANSTART)&&(kudr==0))
                m_d512_r=M512_STARTB;
}
else
{        kudr=UDR;
    if(m_d512_r==M512_STARTB)                //必须有大空挡才开始
    {        m_d512_r=M512_STARTR;
            
            if(kudr==0)                                        //首字节必须为0,否则通讯状态回到空闲
        {        d512_innum=0;
                      cc_indata_num=0;
        }
        else                                
        {        m_d512_r=M512_CANSTART;
        }
        
    }
    else if(m_d512_r==M512_STARTR)
    {        {        ++d512_innum;
                   if(d512_innum>=set_addr)                                //属于自己的数据
                   {        td_indata_now[cc_indata_num]=kudr;         //放入接收缓冲区   
                           ++cc_indata_num;
                      if(cc_indata_num>=TDINMAX)
                       {        m_d512_r=M512_ENDR;                        //这种状态是处理数据
                           UART_IN_DISABLE;                        //关接受   
                       }
                   }
        }            
    }

}
        SREG=sreg;
}


//**************************************************************
//UART发送中断
//**************************************************************
#pragma interrupt_handler uart0_tx_isr:16
void uart0_tx_isr(void)
{        uchar sreg=SREG;
        static uchar cc_outdata_num;        //发送数据计数器
    uchar i;
    //static uchar td_outdata_setnum;
        if(m_d512_r==M512_SFT)                        //发完包头,发第一个数
        {        m_d512_r=M512_SFD;
        cc_outdata_num=0;
        UDR=td_outdata_now[0];
    }
    else if(m_d512_r==M512_SFD)                //继续发数据
    {        ++cc_outdata_num;
            if(cc_outdata_num<TDOUTMAX)
        {        UDR=td_outdata_now[cc_outdata_num];
        }
        else                                                //发完,切换通讯状态
        {        cc_outdata_num=0;
                m_d512_r=M512_SFE;
        }
        
    }

    SREG=sreg;
}

使用特权

评论回复
评论
阮天宇00 2012-12-17 13:08 回复TA
咋们是一个路子的,用define的少,主要加注释 
31
mugenwon| | 2011-11-16 16:09 | 只看该作者
本帖最后由 mugenwon 于 2011-11-16 16:19 编辑

一粘贴TAB格式就不好看了。:o
再来个收数据包的:lol ,够简单吧
个人一般不喜欢用指针,除非速度大小有要求的时候我才用。

//**************************************************************
//UART接收中断
//**************************************************************
#pragma interrupt_handler uart0_rx_isr:14
void uart0_rx_isr(void)
{ uchar k;
static uchar c_pccon;
   
    k=UDR;   
    if(mode_conpc==M_PCIN_INS)  //收到指令包头
    { s_data[0]=k;
     mode_conpc=M_PCIN_LEN;
        
    }
    else if(mode_conpc==M_PCIN_LEN) //收到长度
    { s_data[1]=k;
     c_pccon=0;
     mode_conpc=M_PCIN_DATA;
        
    }
    else if(mode_conpc==M_PCIN_DATA)//收到数据
    { s_data[2+c_pccon]=k;
     c_pccon++;
     if(c_pccon>=s_data[1])
         mode_conpc=M_PCIN_SUM;      
    }
    else if(mode_conpc==M_PCIN_SUM) //收到校验和
    { s_data[2+c_pccon]=k;
     mode_conpc=M_PCIN_DATADO;
     
    }
}

使用特权

评论回复
32
hf5542| | 2011-11-16 16:29 | 只看该作者
围观!

使用特权

评论回复
33
mugenwon| | 2011-11-16 16:29 | 只看该作者
本帖最后由 mugenwon 于 2011-11-16 16:33 编辑

如果要做的好那可不是那么简单。举个例子,假如数据传输了一半,线断了你怎么办?数据总是出错,数据线被长时间拉低,同一条线又要发又要收,能同时做主机和从机,能改变波特率和通讯格式,甚至还要兼顾非标准的UART(例如要做IO口,或者DMX512数据就是)等等。。。

使用特权

评论回复
评论
阮天宇00 2012-12-17 13:09 回复TA
考虑多了就麻烦了,我以前也搜过类似的问题,似乎记得有人说串口慢,没必要搞那么复杂! 
34
shenhao2007| | 2011-11-16 20:06 | 只看该作者
高手甚多

使用特权

评论回复
35
lczsx2000| | 2011-11-17 13:00 | 只看该作者
这么多赞扬的,我来提几个问题,探讨一下吧
1、全局变量太多了
2、都是处理同一个类型的driver程序,是否把全局变量整合成结构体来描述串口这个具体的设备呢
3、void GetFrmData()函数取数据较繁琐,而且没有返回值,不规范
4、int main()函数这样的形式更专业一点吧
5、串口中断程序还是只完成收数据比较好,没必要把状态机放在这里面吧
6、最后,程序里面if和else这样的条件分支太多,程序的逻辑清晰度大大降低

使用特权

评论回复
评分
参与人数 2威望 +3 收起 理由
一路向南 + 2
shizaigaole + 1
36
shizaigaole| | 2011-11-17 14:47 | 只看该作者
楼主的程序不咋地。

37楼说的不错

使用特权

评论回复
37
autopccopy| | 2011-11-17 18:04 | 只看该作者
串口程序,MARK! DING! UP!:lol

使用特权

评论回复
38
hotpower| | 2011-11-17 21:12 | 只看该作者
总结的不错,6条呀。

使用特权

评论回复
39
nayaix| | 2011-11-19 18:01 | 只看该作者
......学习了

使用特权

评论回复
40
Periodic| | 2011-11-20 09:29 | 只看该作者
总体感觉 有点乱

使用特权

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

本版积分规则