打印

linux模拟串口

[复制链接]
4472|9
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
飞鹰嵌入式|  楼主 | 2012-12-17 19:00 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
背景:1、一款只有2个串口的芯片,
           2、需要3个串口
           3、没使用硬件进行串口扩展
基于以上造成了需要模拟串口的后果:
模拟串口步骤
           a、首先创建字符设备驱动
           b、设置定时器,定时器中断中进行发送和接收处理(中断中只做这个事)、定时器中断是波特率的两倍频率,满足采样定理
           c、创建两个内核线程,一个线程用于处理写缓冲,一个线程来处理接收缓存
           d、实现read、write函数,可以两种方式,一是阻塞方式、一是轮询方式,read函数需要和接收缓存线程共同完成、write函数需要和处理写缓存线程共同完成
下面是模拟串口的主要代码
           static irqreturn_t timer_interrupt(int irq,void *id,struct pt_regs *regs)
{

相关帖子

沙发
飞鹰嵌入式|  楼主 | 2012-12-17 19:01 | 只看该作者
static irqreturn_t timer_interrupt(int irq,void *id,struct pt_regs *regs)
{
        static unsigned short tmp_value;
        static unsigned char rx_value;
        static unsigned char tx_en = TRUE;
        static unsigned char RX_flag = FALSE;
        static unsigned char start_flag = FALSE;
        static unsigned char rx_en = FALSE;
        static unsigned char check_rx = 0;
        static unsigned char tx_count = 0;
        static unsigned char rx_count = 0;

        tmp_value = tx_value & 0x0001;
        if(TRUE == TX_flag)//ready for send
        {
                if(TRUE == tx_en)        //send data       
                {
                        gpio_set_value(TXD_PIN,tmp_value);
                        tx_en = FALSE;
                }
                else       //handle data
                {
                        tx_en = TRUE;
                        tx_value = (tx_value >> 1) | 0xfe00;
                        tx_count++;
                }
                if(16 == tx_count) //send bits count
                {
//        printk("tmp_value = %x\n",tmp_value);
                        tx_count = 0;
                        TX_flag = FALSE;
                }
        }
        if(TRUE == RX_flag)//ready for receive
        {

                if(FALSE == rx_en){
                        rx_en = TRUE;
                }
                else //receive data
                {
                        rx_value >>= 1;
                        rx_en = FALSE;
                        if(gpio_get_value(RXD_PIN))
                                rx_value |= 0x80;
                        rx_count++;
                }

                if(8 == rx_count) //receive bits count
                {
                        RX_flag = FALSE;
                //        printk(KERN_INFO"rx = %x\n",rx_value);
                 *m_st_uart0RxBuffer.u8pCurrentPtr = rx_value;                                                     //将接收到的数据放到当前最新接收的数据指针中

                IncRxBuffer0(&m_st_uart0RxBuffer.u8pCurrentPtr,1);
                        }

        }
        else
        {
                        if(gpio_get_value(RXD_PIN)){ //judge start bit
                                RX_flag = FALSE;
                                start_flag = TRUE;
                        }
                        else if(TRUE == start_flag)
                        {
                                RX_flag = TRUE;
                                rx_value = 0;
                                rx_count = 0;
                                start_flag = FALSE;
                        //printk(KERN_INFO"ss\n");
                        }

        }
                return IRQ_HANDLED;
}

使用特权

评论回复
板凳
icecut| | 2012-12-17 19:28 | 只看该作者
搞定了?稳定性如何?

使用特权

评论回复
地板
飞鹰嵌入式|  楼主 | 2012-12-20 10:06 | 只看该作者
icecut 发表于 2012-12-17 19:28
搞定了?稳定性如何?

9600的误码率基本很低

使用特权

评论回复
5
icecut| | 2012-12-20 11:16 | 只看该作者
不错....这种做法值得学习

使用特权

评论回复
6
mr.king| | 2012-12-20 12:18 | 只看该作者
由于系统时钟片问题,可能发送接收异常

使用特权

评论回复
7
飞鹰嵌入式|  楼主 | 2012-12-26 13:00 | 只看该作者
mr.king 发表于 2012-12-20 12:18
由于系统时钟片问题,可能发送接收异常

时钟中断优先级不是最高就容易出现误码

使用特权

评论回复
8
john_lee| | 2012-12-26 14:09 | 只看该作者
民用可以,商用慎重,工业及军用就算了。

使用特权

评论回复
9
1187571764| | 2012-12-26 14:11 | 只看该作者
初学ARM的朋友们是否有很多的疑惑,ARM 模块、开发板,销售中提供技术支持

使用特权

评论回复
10
1187571764| | 2012-12-26 14:12 | 只看该作者
如有需要请联系胡** :60494890

使用特权

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

本版积分规则

个人签名:

46

主题

452

帖子

4

粉丝