GEC210(S5PV210)裸机驱动之串口及串口中断

来源:互联网 发布:ubuntu搭建案桌模拟器 编辑:程序博客网 时间:2024/06/05 02:50

主机平台:Linux CentOS 6.5

arm平台:粤嵌GEC210开发板(S5PV210)


这次写一下串口的驱动,功能是在linux终端中键入并向arm发送一个字符,arm返回这个字符将其在终端上显示。

其中,串口采用串口0,非FIFO模式,波特率115200,8位数据为,无较检位,接收用中断方式,发送用查询方式。


既然用到中断,那还是按就之前写中断的步骤进行:

(1--7步是中断通用部分,依然省略,不懂的话看我的另一篇文章:GEC210(S5PV210)裸机驱动之中断系统)

8.编写外设对应的中断服务程序

8.1.根据标志为判断发生了什么中断。(当多个中断共享一个中断号时通常需要做此判断)

8.2.根据发生的中断执行相应的任务

8.3.清除所发生中断的中断标志位

8.4.清除全部VICxADDR(置0)

8.5.重新使能全局IRQ中断(进入中断后,全局IRQ中断会被关闭)


9.设置外设寄存器初始化外设(包括清除中断标志位,使能中断等操作)

9.1.关闭外设寄存器的中断使能

9.2.清除外设中断标志位

9.3.初始化设置与外设相关的其它寄存器。例如I/O的功能选择(这个容易忘记),设置输入时钟频率等等。

9.4开启外设对应中断

10.根据外设查找中断源表获得其中断号

11.根据中断号设置对应的中断服务程序入口地址寄存器(VICxVECTADDRx)

12.根据中断号使能对应中断


下面就是针对串口将每个步骤具体化:

8.编写外设对应的中断服务程序

8.1.判断该次中断是否串口的发送中断、接收中断、还是错误中断

8.2.执行对应任务,此处是只当为接收中断时,通过查询方式将获得的数据发送出去

8.3.清除对应中断标志位(UINTSP0和UINTP0)

8.4.清除全部VICxADDR(置0)

8.5.重新使能全局IRQ中断(进入中断后,全局IRQ中断会被关闭)


9.设置外设寄存器初始化外设(包括清除中断标志位,使能中断等操作)

9.1.关闭串口0中断使能(UINTM0[3:0])

9.2.清除串口0中断所有标志位 (UINTSP0[3:0]和UINTP0[3:0])

9.3

(1)将串口0对应的IO引脚功能设置为UART_0_RXDGPA0CON[3:0] 和 UART_0_TXD(GPA0CON[7:4])

(2)设置波特率。波特率由PCLK时钟、UCON[10]、UBRDIV、UDIVSLOT寄存器确定


公式:

DIV_VAL = UBRDIVn + (num of 1's in UDIVSLOTn)/16DIV_VAL = (PCLK / (bps x 16)) −1orDIV_VAL = (SCLK_UART / (bps x 16)) −1
此处,时钟源选择PCLK(UCON[10]=0),为66M,且UDIVSLOTn=0,因此由第1、2条公式得:

UBRDIV0 = (66M/(115200*16))-1 = 35

(3)设置帧格式,包括数据位位数、停止位位数、较检方式(ULCON0)

(4)配置UCON寄存器,里面有很多设置,我讲一些个人认为比较重要的,其它没看懂的话就保持默认值吧

[10]:波特率时钟源选择位

[9:8]:Tx/Rx Interrupt Type:手册上写这两位必须置1

[5]:Loop-back Mode ,即回环测试模式,可以自发自收

[3:2]:Transmit Mode:什么情况下允许写串口发送寄存器 00:不可写;01:可通过中断或查询方式写入;10:在DMA模式下可写

[1:0]:Receive Mode:什么情况下允许读串口接收寄存器 00:不可写;01:可通过中断或查询方式写入;10:在DMA模式下可写

9.4.使能串口中断,这里只使能接收中断(UINTM0[0])


10.根据外设查找中断源表获得其中断号,可知中断号为42

11.根据中断号设置对应的中断服务程序入口地址寄存器(VIC3VECTADDR10)

12.根据中断号使能对应中断(VIC3INTENABLE[10])


跟着再讲下如何发送和接收,这里比较简单

发送:先判断串口是否空闲,然后向发送缓冲寄存器写入数据

接收:在中断中直接读接收缓冲寄存器就可以了


具体实现看下面代码:

void uart0_int_func(){    unsigned long temp;    if(UTRSTAT0&0x1)   //判断是否为接收中断    {        temp=URXH0;                         //读取接收寄存器        while(!(UTRSTAT0&0x2));    //等待串口空闲        UTXH0=temp;               <span style="font-size:14px;">//</span>发送接收到的内容                UINTSP0|=0xf;                //清除中断标志位        UINTP0|=0xf;                 //清除中断标志位        clear_vicaddress();          <span style="font-size:14px;">/</span>/清除全部VICADDR寄存器    }    enable_global_IRQ();             //使能全局IRQ中断        }void uart0_init(){    ULCON0|=0x3;                  //设置帧格式    UCON0=0x305;                //时钟源、读写发送接收寄存器模式    UBRDIV0=35;                   //设置波特率    UINTM0=0xf;                    //屏蔽所有串口中断    GPA0CON=0x22;         //设置引脚功能为串口收发    UINTSP0|=0xf;         //清除中断标志    UINTP0|=0xf;          //清除中断标志                set_int_vectaddr(42,uart0_int_func);  //设置42号中断服务程序入口地址    interrupt_enable(42);                            //使能中断系统42号中断    UINTM0=0xe;                                        //使能串口接收中断    }


好了,这就是一个简单的串口程序,串口还有很多种模式的例如FIFO、Infrared、DMA等模式,这些就要以后慢慢去深入学习了。













0 0
原创粉丝点击