加入收藏 | 设为首页 | 会员中心 | 我要投稿 | RSSRSS-巴斯仪表网
您当前的位置:首页 > 电子发烧 > 单片机学习

uart驱动(for keil rtx)

时间:2013-11-23  来源:123485.com  作者:9stone

#define UART0_BPS   9600

#define UART0_RXBUF_SIZE 32
#define    UART0_TXBUF_SIZE 32

#define UART_NO_ERR     0
#define UART_TX_EMPTY   1

extern void uart0_init (void);
extern void uart0_putc (uint8_t c);
extern void uart0_puts (uint8_t *pbuf, uint16_t len);
extern uint8_t uart0_getc (void);

typedef struct {
    OS_SEM      rx_sem;                     // Rx信号量
    uint16_t    rx_cnt;                     // Rx缓冲中字符数
    uint8_t     *rx_pi;                     // 指向下一字符将被插入的位置
    uint8_t     *rx_po;                     // 指向下一字符将被提取的位置
    uint8_t     rx_buf[UART0_RXBUF_SIZE];   // Rx缓冲
   
    OS_SEM      tx_sem;                     // Tx信号量
    uint16_t    tx_cnt;                     // Tx缓冲中字符数
    uint8_t     *tx_pi;                     // 指向下一字符将被插入的位置
    uint8_t     *tx_po;                     // 指向下一字符将被提取的位置
    uint8_t     tx_buf[UART0_TXBUF_SIZE];   // Tx缓冲
    uint8_t     tx_busy;                    // Tx忙标志

} UART0_BUF;

static UART0_BUF uart0_buf;
static UART0_BUF *pbuf0 = &uart0_buf;

void uart0_putrx (uint8_t c)
{
    if (pbuf0->rx_cnt < UART0_RXBUF_SIZE) {
        pbuf0->rx_cnt++;
        *pbuf0->rx_pi++ = c;
        if(pbuf0->rx_pi == &pbuf0->rx_buf[UART0_RXBUF_SIZE]) {
            pbuf0->rx_pi = &pbuf0->rx_buf[0];
        }
        isr_sem_send (pbuf0->rx_sem);
    }
}

uint8_t uart0_gettx (uint8_t *perr)
{
    uint8_t    c;

    if (pbuf0->tx_cnt > 0) {
        pbuf0->tx_cnt--;
        c = *pbuf0->tx_po++;
        if (pbuf0->tx_po == &pbuf0->tx_buf[UART0_TXBUF_SIZE]) {
            pbuf0->tx_po = &pbuf0->tx_buf[0];
        }
        isr_sem_send (pbuf0->tx_sem);
        *perr = UART_NO_ERR;
        return (c);
    } else {
        *perr = UART_TX_EMPTY;
        return (0);
    }
}

void uart0_proc (void) __irq
{
    uint8_t iir, c;
    uint8_t i, err;
   
    while (((iir = U0IIR) & 0x01) ==0) {
        switch (iir & 0x0E) {
        case 0x04:
        case 0x0C:
        for (i=0; i<16; i++) {
            if ((U0LSR & 0x01)==0) break;
            uart0_putrx (U0RBR);
        }
        break;

        case 0x02:
        for (i=0; i<16; i++) {
            c = uart0_gettx (&err);
            if (err == UART_NO_ERR) {
                U0THR = c;
            } else {
                pbuf0->tx_busy = 0;
                break;
            }
        }
        break;
        }
    }
     
    VICVectAddr = 0x00;
}

void uart0_init (void)
{
    PINSEL0 &= 0xFFFFFFF0;
    PINSEL0 |= 0x00000005;

    U0LCR = 0x83;
    U0DLM = (FPCLK / 16) / UART0_BPS / 256;
    U0DLL = (FPCLK / 16) / UART0_BPS % 256;
    U0LCR = 0x03;
    U0FCR = 0x87;
    U0IER = 0x03;

    pbuf0->rx_cnt = 0;
    pbuf0->rx_pi  = &pbuf0->rx_buf[0];
    pbuf0->rx_po  = &pbuf0->rx_buf[0];
    os_sem_init (pbuf0->rx_sem, 0);
    pbuf0->tx_cnt = 0;
    pbuf0->tx_pi  = &pbuf0->tx_buf[0];
    pbuf0->tx_po  = &pbuf0->tx_buf[0];
    os_sem_init (pbuf0->tx_sem, UART0_TXBUF_SIZE);
    pbuf0->tx_busy = 0;

    VICVectCntl0 = 0x26;
    VICVectAddr0 = (uint32_t)uart0_proc;
    VICIntEnable|= 0x40;
}

uint8_t uart0_getc (void)
{  
    uint8_t c;

    os_sem_wait (pbuf0->rx_sem, 0xFFFF);
    irq_lock ();
    pbuf0->rx_cnt--;
    c = *pbuf0->rx_po++;
    if (pbuf0->rx_po == &pbuf0->rx_buf[UART0_RXBUF_SIZE]) {
        pbuf0->rx_po = &pbuf0->rx_buf[0];
    }
    irq_unlock ();
    return (c);
}

void uart0_putc (uint8_t c)
{
    os_sem_wait (pbuf0->tx_sem, 0xFFFF);
    irq_lock ();
    pbuf0->tx_cnt++;
    *pbuf0->tx_pi++ = c;
    if (pbuf0->tx_pi == &pbuf0->tx_buf[UART0_TXBUF_SIZE])  {
        pbuf0->tx_pi = &pbuf0->tx_buf[0];
    }
    if (pbuf0->tx_busy == 0) {
        pbuf0->tx_busy = 1;
        pbuf0->tx_cnt--;
        c = *pbuf0->tx_po++;
        if (pbuf0->tx_po == &pbuf0->tx_buf[UART0_TXBUF_SIZE]) {
            pbuf0->tx_po = &pbuf0->tx_buf[0];
        }
        os_sem_send (pbuf0->tx_sem);
        U0THR = c;
    }
    irq_unlock ();
}

void uart0_puts (uint8_t *pbuf, uint16_t len)
{
    while (len--) {
        uart0_putc (*pbuf++);    
    }
}


分享到:
来顶一下
返回首页
返回首页
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表
栏目导航->单片机学习
  • 电子应用基础
  • 电源技术
  • 无线传输技术
  • 信号处理
  • PCB设计
  • EDA技术
  • 单片机学习
  • 电子工具设备
  • 技术文章
  • 精彩拆解欣赏
  • 推荐资讯
    使用普通运放的仪表放大器
    使用普通运放的仪表放
    3V与5V混合系统中逻辑器接口问题
    3V与5V混合系统中逻辑
    数字PID控制及其改进算法的应用
    数字PID控制及其改进
    恶劣环境下的高性价比AD信号处理数据采集系统
    恶劣环境下的高性价比
    栏目更新
    栏目热门