• 八、mini2440裸机程序之UART(2)UART0与PC串口通信【转】


    1.相关原理图

     

    2.相关寄存器介绍与配置

        1)与管脚相关

    ①GPHCON

    注:

    配置成UART0功能:

    GPHCON |= 10 10 10 10b(还要在GPHUP里把管脚禁止上拉)

        2)与中断相关


    上传图片好麻烦,跟以前相关的这里就不贴了

        3)与UART0相关

    ①ULCON0   

    注:

    Infrared Mode :选择普通模式

    Parity Mode : 选择不执行奇偶校验

    Number of stop :选择1个结束位

    Word length :8-bits字长

    ULCON0 = 0x03

    ②UBRDIV0和UCON0

    注:

    UBRDIVn      =  (int)(UART clock /(baud rate * 16)) - 1,因为下面我们选择了PCLK作为UARTclock。所以UBRDIV0=(int)PCLK/(baudrate*16)) - 1。其中PCLK=101.25MHz,波特率选择115200

    UBRDIV0=(int)(     101250000/(115200*16)   ) - 1 = 54.

    选择UBRDIV0= 0x36

     

    注:

    Clock selection :时钟源选择,选择PCLK,根据上个定时器实验得知PCLK使用101.25MHz。00b

     

    注:

    脉冲触发:指的是在Tx buffer从有数据跳变为空时(对于接收模式来说,则是Rx buffer从空跳变为有数据)触发一次边沿中断,之后即使为空,但是没有这个跳变是不会触发中断的(Non-FIFO)。对于使用FIFO来说,一旦到达Tx/Rx FIFO的触发水平时才产生一个边沿中断,其它时候都不会触发中断。

    水平触发:指的是只要Tx buffer为空(对于接收模式来说,则是只要Rx buffer有数据)则一直产生中断请求 (电平中断)。对于使用FIFO来说,只要是高于(接收模式)/低于(发送模式)或等于触发水平就一直产生中断(电平中断)。

       

    ①如果发送中断采用了脉冲触发,在发送中断处理里执行太长时间的情况下,导致下个脉冲中断请求在中断处理函数里产生了,那么如果请求中断请求位是在后面清除的,则会引起下个脉冲中断请求被清除了而无法再次进入发送中断(因为数据已经被发送出去了,则不会再达到触发水平(FIFO)或者从从有数据到空的跳变(non-FIFO))。而如果是采用水平触发则不会发生这种情况,因为只要是空的(non-FIFO)或低于等于触发水平(FIFO),即便被清除了请求位,还是会产生请求,但是这样会连绵不断的触发中断。

    ②如果接收中断采用了脉冲触发,在接收中断处理里执行太长时间的情况下,也会导致下一个脉冲中断请求在中断处理函数里产生了,那么如果请求中断请求位是在后面清除的,则会引起下个脉冲中断请求被清除了而无法再次进入发送中断(因为之前的数据还没被取出,则不会再达到触发水平(FIFO)或者从空到有数据的跳变(non-FIFO))。而如果是采用水平触发则不会发生这种情况,因为只要有数据(non-FIFO)或高于等于触发水平(FIFO),即便被清除了请求位,还是会产生请求,但是这样会连绵不断的触发中断。

    举个栗子:

    ①只使能发送中断,选择FIFO,触发水平为empty,在发送中断里发送一个字节,延迟3秒,这段时间足够让Tx FIFO里从一个数据跳变到empty(2),即发送中断请求(1)在中断处理函数里产生了。

    ·使用脉冲触发:退出中断处理函数清除了中断请求,也就把(1)给清掉了,进不了发送中断无法给数据,并且Tx FIFO一直为空(无法出现(2)) , 因此不再产生中断。

    ·使用水平触发:退出中断处理函数清除了中断请求,也把(1)给清掉了,但是只要是低于或等于empty在FIFO里,则电平中断还会产生,能够再次进入中断。

    ②只使能接收中断,选择FIFO,触发水平为1-byte,PC机上发一个字节触发中断,在接收中断里接收一个字节,延迟3秒,在这段时间里再发1个字节,这样会有一个从empty到1-byte的跳变(2),这样就在中断服务函数里产生了中断请求,即接收中断请求(1)在中断处理函数里产生了。

    ·使用脉冲触发:退出中断处理函数清除了中断请求,也就把(1)给清掉了,进不了接收中断无法取出数据,并且Rx FIFO一直1-byte数据(无法出现(2)) ,因此不再产生中断。

    ·使用水平触发:退出中断处理函数清除了中断请求,也把(1)给清掉了,但是只要是高于或等于1-byte数据在FIFO里,则电平中断还会产生,能够再次进入中断。

    经测试成立。

    Tx interrupt type :保险点选择水平触发就行了,不过这个我们只在需要发送数据再打开,发送完数据再关闭,这样就防止老是进入中断。1b

    Rx interrupt type :同理 ,选择水平触发就好了,只要有数据就进入中断处理数据。1b

    Rx timeout enable :选择禁止。0b

    Rx error status interrupt enable :禁止接收错误状态中断。0b

    Loopback mode :选择普通模式。0b

    Send break signal :选择正常传输。0b

    注:

    Transmit mode :选择中断请求或者轮询模式。01b

    Receive mode :选择中断模式或者轮询模式。01b

    UCON0  = 0x305

    ③UFCON0

    注:

    Tx FIFO trigger level :选择emply,只有在FIFO到达空了才会触发中断。00b

    Rx FIFO trigger level :选择1-bype,这样只要接收到1个字节就直接进入中断取出处理。00b

    Tx FIFO reset :选择normal。0b

    Rx FIFO reset :选择normal。0b

    FIFO enable :使能FIFO。1b

    UFCON0 = 0x01

    ④UMCON0

    注:

    AFC flow control:不使能自动流控。0b

    Request to send:不使能自动流控,这个位也不需要用到

    初始化时:UMCON0 = 0;

    ⑤UTRSTAT0

    注:只读

    Transmitter empty:当发送缓冲寄存器(FIFO)已经没有有效数据可以发送并且发送数据移位器为空。该域会被置为‘1’。

    Transmit buffser empty:当发送缓冲寄存器空时被置为‘1’。(只针对于Non-FIFO,Tx FIFO模式需要检测UFSTAT寄存器的count 位和Tx FIFO Full 位)

    Receive buffer data ready:当接收缓冲寄存器包含了从PXDn端口接收到的有效数据时被设置为‘1’。(只针对于Non-FIFO,Rx FIFO模式需要检测UFSTAT寄存器的count位和Rx FIFO Full 位)

    ⑥UERSTAT0

    注:(当这个状态寄存器被读取时会自动清零)

    Break detect:当一个break 信号被接收到了这个位会被置‘1’。

    Frame Error :当一个帧错误在接收操作期间产生时被置‘1’。

    Parity error :当一个奇偶校验错误在接收期间产生时被置‘1’。

    Overrun error:当一个overrun错误在接收期间产生时被置‘1’。

    ⑦UFSTAT0

    注:

    Tx FIFO full :当发送FIFO在发送期间满了,这个位会被置‘1’。

    Tx FIFO count :Tx FIFO里的data数。

    Rx FIFO Full :当接收FIFO在接收期间满了,这个位会被置‘1’。

    Rx FIFO count :Rx FIFO里的data数。

    ⑧UMSTAT0

    注:

    Delta CTS:指明了nCTS输入到S3C2440A状态是否改变了知道该位被CPU读取了才自动清零。

    Clear to send:要发送数据时需要检查该位是否有效,有效才可以写数据到Tx FIFO。

    这两个都用在自动流控功能里。如果双方都不使用自动流控。这个也可以不管。

    ⑨UTXH0(UART0发送缓冲寄存器)

    注:

    TXDATA0:存放用户要发送的数据

    ⑩URXH0(UART0接收缓冲寄存器)

    注:

    (当overrun error发生时,URXH0必须被读出,否则,下一个接收到的数据也会造成overrun error尽管UERSTAT0的overrun位已经被清除了)

    RXDATA:存放接收到的数据

    3.流程图设计

        ①主流程图

                                                                            

        ②中断处理子程序

                                                                                  

        ③中断服务子函数

                                                  

    4.程序设计

         ①Makefile

    uart0.bin : head.o demoUart0.o
        arm-linux-ld -Tuart0.lds -o uart0_elf $^
        arm-linux-objcopy -O binary -S uart0_elf $@
        arm-linux-objdump -D -m arm uart0_elf > uart0.dis

    %.o : %.S
        arm-linux-gcc -Wall -c -o $@ $<

    %.o : %.c
        arm-linux-gcc -Wall -c -o $@ $<
    clean:
        rm -f uart0.dis uart0.bin uart0_elf *.o *.bak 

    /****************************************************************************************************************************/

         ②uart0.lds

    SECTIONS { 
        first    0x00000000 : { head.o }
        second    0x30000000 : AT(2048) { demoUart0.o }

    /*****************************************************************************************************************************/

           ③head.S

    @与内存相关
    .equ    BWSCON   ,    0x48000000
    .equ    BANKCON6 ,     0x4800001C
    .equ    REFRESH  ,    0x48000024
    .equ    BANKSIZE ,    0x48000028
    .equ    MRSRB6     ,    0x4800002C

    @与中断相关
    .equ    INTMSK    ,    0x4A000008
    .equ  INTSUBMSK    ,    0x4A00001C
    .equ  SUBSRCPND ,    0x4A000018
    .equ    SRCPND    ,    0x4A000000
    .equ    INTPND    ,    0x4A000010

    @与看门狗相关
    .equ    WTCON    ,    0x53000000

    @与管脚配置相关的
    .equ    GPHCON    ,    0x56000070
    .equ    GPHUP    ,    0x56000078

    @与UART0配置相关的
    .equ    ULCON0    ,    0x50000000
    .equ    UBRDIV0    ,    0x50000028
    .equ    UCON0   ,    0x50000004
    .equ    UFCON0    ,    0x50000008
    .equ    UMCON0    ,    0x5000000C
    .equ   UTRSTAT0    ,    0x50000010    @read-only
    .equ   UERSTAT0    ,    0x50000014
    .equ    UFSTAT0    ,    0x50000018
    .equ    UMSTAT0    ,    0x5000001C
    .equ    UTXH0    ,    0x50000020    @little-endian
    .equ    URXH0    ,    0x50000024    @little-endian

    @时钟相关寄存器
    .equ    MPLLCON    ,    0x4C000004
    .equ    UPLLCON    ,    0x4C000008
    .equ    CLKDIVN    ,    0x4C000014
    .equ    CAMDIVN ,    0x4C000018

    @与灯光配置相关的
    .equ    GPBCON    ,    0x56000010
    .equ    GPBDAT    ,    0x56000014

    .text
    .global _start
    _start:
    /***********设置中断向量表*************/
        b    ResetInit    @复位异常入口
    HandlerUndef:
        b    HandlerUndef    @未定义异常入口
    HandlerSWI:
        b    HandlerSWI    @软中断异常入口
    HandlerPabort:
        b    HandlerPabort    @取指中止异常入口
    HandlerDabort:
        b    HandlerDabort    @数据中止异常入口
    HandlerNotUsed:
        b    HandlerNotUsed    @保留

        b    HandlerIRQ    @中断异常入口
    HandlerFIQ:
        b    HandlerFIQ    @快中断异常入口
    /************END设置中断向量表***********/

    ResetInit:
    /*************关闭看门狗****************/
        ldr    r0 , =WTCON
        mov    r1 , #0x0
        str    r1 , [r0]
    /************END关闭看门狗**************/

    /**********初始化LED灯管脚************
        @把LED1-4管脚置为输出
        ldr    r0 , =GPBCON
        ldr    r1 , [r0]        @把GPBCON里的内容加载到r1里
        ldr    r2 , =(0xFF<<10)
        bic    r1 , r1 ,r2    @操作数取反码或上r1,用于清零工作
        ldr    r2 , =(0x55<<10)
        orr    r1 , r1 , r2 
        str    r1 , [r0]
        
        ldr    r0 , =GPBDAT
        ldr    r1 , [r0]    
        ldr    r2 , =(0x0F<<5)
        bic    r1 , r1 , r2
        orr    r1 , r1 , r2
        str    r1 , [r0]
    ***********END***************/    

    /**********初始化相关管脚为UART0功能************/
        ldr    r0 , =GPHCON
        ldr    r1 , [r0]        @把GPHCON里的内容加载到r1里
        ldr    r2 , =0xFF
        bic    r1 , r1 ,r2    @操作数取反码&r1,用于清零
        ldr    r2 , =0xAA
        orr    r1 , r1 , r2 
        str    r1 , [r0]    
        
        ldr    r0 , =GPHUP
        ldr    r1 , [r0]
        bic    r1 , r1 , #0x0f
        orr    r1 , r1 , #0x0f
        str    r1 , [r0]    @管脚禁止上拉功能
    /***********END***************/    


    /***********配置时钟相关寄存器***********/
        ldr    lr , =Memconf
        ldr    pc , =ClkConfigure
    /**********END配置时钟相关寄存器*********/

        
    /***********配置内存相关寄存器***********/
    Memconf:
        ldr    lr , =InitSystemSp
        ldr    pc , =MemConfigure
    /**********END配置内存相关寄存器*********/


    /***********设置系统模式下的sp***********/
    InitSystemSp:
        @复位默认进入系统模式
        ldr    sp , =0x34000000
    /********END设置系统模式下的sp***********/


    /**********配置UART0相关寄存器***********/
        ldr    lr , =CopyToSdram
        ldr    pc , =Uart0Configure
    /*******************END******************/

    /************拷贝中断处理子函数到内存****/
    CopyToSdram:
        ldr    lr , =Uart0IntConf
        ldr    pc , =copy_bootsram_to_sdram
    /*******************END******************/

    /********配置UART0中断相关寄存器*******/
    Uart0IntConf:
        ldr    r0 , =INTMSK     @使能UART0中断
        ldr    r1 , [r0]
        bic    r1 , r1 , #(0x01<<28)
        str    r1 , [r0]
        
        ldr    r0 , =INTSUBMSK        @禁止INT_ERR0(1<<2),
        ldr    r1 , [r0]        @使能INT_TXD0(0<<1),INT_RXD0(0<<0),中断
        bic    r1 , r1 , #0x07
        orr    r1 , r1 , #0x06
        str    r1 , [r0]
    /******END配置UART0中断相关寄存器******/


    /*进入中断模式设置中断模式下的sp退出到系统模式
    *使能IRQ中断*/    
        msr    cpsr_c , 0xd2        @进入中断模式,禁止中断,其中cpsr后的_c表示cpsr[7:0]
        ldr    sp , =0x33500000    @设置sp
        msr    cpsr_c , 0x5f        @退出到系统模式,使能IRQ中断
    /*END进入中断模式设置中断模式下的sp退出到系统模式*/


    /*************等待中断******************/
    halt_loop:
        b    halt_loop
    /*********************END****************/    
        
        
        
    /*************IRQ中断服务子程序**********/
    HandlerIRQ:

        @因为在产生中断异常时,lr存的是当前指令的下一条指令,所以要减四
        sub    lr , lr , #4
        
        @把相关寄存器压入中断模式下的栈
        @db表示sp每次传送内容前减1
        stmdb    sp! , {r0-r12 , lr}
        
        @禁止IRQ中断
        mrs    r1 , cpsr_all
        orr    r1 , r1 , #(1<<7) 
        msr    cpsr_all , r1
        
        @调用中断服务处理函数
        ldr    lr , =IRQ_Return
        ldr    pc , =main
        
    IRQ_Return:
    /*    ldr    r0 , =GPBDAT
        ldr    r1 , [r0]    
        ldr    r2 , =(0x0F<<5)
        bic    r1 , r1 , r2
        orr    r1 , r1 , r2
        str    r1 , [r0]*/
        @把栈里面的内容推出到相应寄存器里,并把lr推到pc寄存器实现跳转
        @ia表示每次传送后加1 , 当寄存器列表中包含了pc寄存器,选用^为后缀,就会把spsr拷贝到cpsr
        ldmia    sp! , {r0-r12 , pc}^

            
    /********END IRQ中断服务子程序***********/


    /*配置Uart0相关寄存器*/
    Uart0Configure:
        ldr    r0 , =ULCON0
        mov    r1 , #0x03
        str    r1 , [r0]    @普通模式,禁止奇偶校验,1个结束位,8-bit字长
        
        ldr    r0 , =UBRDIV0
        mov    r1 , #0x36      
        str    r1 , [r0]    @波特率选择115200,所以UBRDIV0=54
        
        ldr    r0 , =UCON0
        ldr    r1 , =0x305
        str    r1 , [r0]    @时钟源=PCLK
                    @Rx,Tx水平触发,禁止接收超时中断,禁止接收错误状态中断,
                    @不使用回路模式,不发送break信号
                    @中断方式发送接收数据到缓冲寄存器
        ldr    r0 , =UFCON0
        mov    r1 ,#0x01
        str    r1 , [r0]    @Tx FIFO触发水平选择空时触发,
                    @Rx FIFO触发水平选择>=1字节触发
                    @使能FIFO
        
        ldr    r0 , =UMCON0
        mov    r1 , #0x0
        str    r1 , [r0]    @禁止自动流控功能。
        
        bx    lr
        
    /******************END******************/

    /***********配置时钟相关寄存器***********/
    ClkConfigure:
        @UPLL选择MDIV=0x38,PDIV=2,SDIV=1.得UPLL clock=96MHz
        @这里先设置UPLL是为了与设置MPLL隔开至少7个NOP的时间间隔
        ldr    r0 , =UPLLCON
        ldr    r1 , =(0x38<<12)|(0x02<<4)|(0x01<<0)
        str    r1 , [r0]
        
        @分频比FCLK:HCLK:PCLK=1:4:4 , UCLK=UPLL_clock/2=48MHz
        ldr    r0 , =CLKDIVN
        mov    r1 , #(0x01<<3)|(0x02<<1)|(0x00<<0)
        str    r1 , [r0]    
        ldr    r0 , =CAMDIVN
        ldr    r1 , [r0]
        bic    r1 , r1 , #(0x03<<8)
        str    r1 , [r0]
        
        @因为HDIVN不是0 , 所以CPU总线模式要从高速总线模式改变
        @为异步总线模式
        mrc    p15 , 0 , r1 , c1 , c0 , 0
        orr    r0 , r0 , #0xC0000000
        mcr    p15 , 0 , r0 , c1 , c0 , 0

        @MPLL选择MDIV=0x7f,PDIV=2,SDIV=1,得MPLL clock=405MHz 
        ldr    r0 , =MPLLCON
        ldr    r1 , =(0x7f<<12)|(0x02<<4)|(0x01<<0)
        str    r1 , [r0]
        
        bx    lr
    /***************END*************************/

    /*******内存初始化子程序*********/
    MemConfigure:
        @BWSCON[27:24] = 0 0 10B
        ldr    r0 , =BWSCON
        ldr    r1 , [r0]
        ldr    r2 , =(0x0F<<24)
        bic    r1 , r1 , r2
        ldr    r2 , =(0x02<<24)
        orr    r1 , r1 , r2
        str    r1 , [r0]    

        @BANKCON6[16:15]=11B,BANKCON6[3:0]=00 01B
        ldr    r0 , =BANKCON6
        ldr    r1 , [r0]
        ldr    r2 , =(0x03<<15)
        bic    r1 , r1 , r2
        orr    r1 , r1 , r2
        ldr    r2 , =0x0F
        bic    r1 , r1 , r2
        ldr    r2 , = 0x01
        orr    r1 , r1 , r2
        str    r1 , [r0]

        @这里的Trp要大于20ns , Trc要大于70ns,HCLK=101.25MHz
        @故时钟周期=1s/HCLK=9.8ns,Trp*9.8>20ns ==> Trp>=3 ==> Trp域=01b 
        @Trp*9.8+Tsrc*9.8>70ns ==> Tsrc>=5 ==> Tsrc域=01b
        @REFRESH[23:18] = 1 0 01 01B,REFRESH[10:0] = 0x4E8
        ldr    r0 , =REFRESH
        ldr    r1 , [r0]
        ldr    r2 , =(0x3F<<18)
        bic    r1 , r1 , r2
        ldr    r2 , =(0x25<<18)
        orr    r1 , r1 , r2
        ldr    r2 , =0x7FF
        bic    r1 , r1 , r2
        ldr    r2 , =0x4E9
        orr    r1 , r1 , r2
        str    r1 , [r0]

        @BANKSIZE[7:0] = 1 0 1 1 0 001 B
        ldr    r0 , =BANKSIZE
        ldr    r1 , [r0]
        ldr    r2 , =0xFF
        bic    r1 , r1 , r2
        ldr    r2 , =0xB1
        orr    r1 , r1 , r2
        str    r1 , [r0]    

        @MRSRB6[11:0] = 0 00 011 0 000 B
        ldr    r0 , =MRSRB6
        ldr    r1 , [r0]
        ldr    r2 , =0x3FF
        bic    r1 , r1 , r2
        ldr    r2 , =0x030
        orr    r1 , r1 , r2
        str    r1 , [r0]    

        bx    lr    @函数返回
    /******END内存初始化子程序*******/



    /******拷贝后2048到4096之间的代码到sdram*******/
    copy_bootsram_to_sdram:
        ldr    r0 , =0x800
        ldr    r1 , =0x30000000
        ldr    r2 , =0x1000
    copy:
        ldr    r3 , [r0] , #4
        str    r3 , [r1] , #4
        cmp    r0 , r2
        bne    copy
        bx    lr
    /*****END拷贝前4K代码到sdram*****/

    /****************************************************************************************************************/

         ④demoUart0.h


    #ifndef    DEMOUART0_H
    #define DEMOUART0_H

    #define    GPBCON        (*(volatile unsigned long *)0x56000010)
    #define    GPBDAT        (*(volatile unsigned long *)0x56000014)

    #define    INTOFFSET    (*(volatile unsigned long *)0x4A000014)
    #define SRCPND        (*(volatile unsigned long *)0x4A000000)
    #define INTPND        (*(volatile unsigned long *)0x4A000010)
    #define    SUBSRCPND    (*(volatile unsigned long *)0x4A000018)
    #define INTSUBMSK    (*(volatile unsigned long *)0x4A00001C)

    #define    UTXH0        (*(volatile unsigned long *)0x50000020)
    #define URXH0        (*(volatile unsigned long *)0x50000024)
    #define    UFSTAT0        (*(volatile unsigned long *)0x50000018)
    #define    UMCON0        (*(volatile unsigned long *)0x5000000C)

    #define    INT_TXD0    (0x01<<1)
    #define    INT_RXD0    (0x01)

    #define    TFIFO_FULL    (0x01<<14)    
    #define    RFIFO_DATA_NUM    (0x1f)

    /*消息队列大小*/
    #define    QUEUE_SIZE    100
    unsigned char p[QUEUE_SIZE];
    /*
    *选择了水平触发所以这里可以直接把所以中断请求清除,
    *退出之后只要满足触发条件还是会触发中断
    **/
    #define    cleanIQR()
        do {
            SUBSRCPND = SUBSRCPND;
            SRCPND = SRCPND;
            INTPND = INTPND;
        } while(0)

        
    /*接收数据的消息队列结构体*/    
    typedef    struct MSG_QUEUE 
    {
        unsigned char *Qmsg;
        unsigned char *write;
        unsigned char *read;
        unsigned char size;
    } MSG_QUEUE;

    /***************函数声明********************/
    /*把消息队列qmsg里的消息通过uart0发送出去*/
    void uart0_sent_msg(MSG_QUEUE *qmsg);

    /*把接收到的消息存入到qmsg消息队列里*/
    void uart0_revice_msg(MSG_QUEUE *qmsg);

    /*延时函数*/
    void delay(volatile unsigned long second);
    /*******************************************/



    /*********************函数定义************************/

    void delay(volatile unsigned long second)
    {
        volatile unsigned long i;
        while(second--){
            i=1000000;
            while(--i);
        }    
    }

    void uart0_sent_msg(MSG_QUEUE *qmsg)
    {
        while( !(UFSTAT0&TFIFO_FULL) && qmsg->size ) {
        /*如果Tx FIFO还被满,并且队列还有数据要发送,则一直循环填入UTXH0*/
        
            UTXH0 = *qmsg->read++;
            --qmsg->size;    
            
            if(qmsg->read == (qmsg->Qmsg+QUEUE_SIZE-1) ){
                qmsg->read = qmsg->Qmsg;    
            }
        }    
        return ;        
    }

    void uart0_revice_msg(MSG_QUEUE *qmsg)
    {
        while( (UFSTAT0 & RFIFO_DATA_NUM) && (qmsg->size < QUEUE_SIZE) ){   
        /*如果接收FIFO里还有数据并且消息队列uart0_qmsg里数据没满,则继续取出数据*/
        
            *qmsg->write++ = (volatile unsigned char)URXH0;
            ++qmsg->size;
            
            if(qmsg->write == (qmsg->Qmsg+QUEUE_SIZE-1) ) {
                qmsg->write = qmsg->Qmsg;    
            }    
        }    
        return;
    }

    /******************************************/
    #endif

    /***********************************************************************************************************************/

         ⑤demoUart0.c

    #include "demoUart0.h"


    int main()
    {
        
        static unsigned char i;
        static MSG_QUEUE *uart0_qmsg;

        if( INTOFFSET != 28 ){
            cleanIQR();
            return 0;    
        }
        
        /*第一次进来初始化队列*/
        if(i==0){
            uart0_qmsg->Qmsg = p;
            uart0_qmsg->write = p;
            uart0_qmsg->read = p;
            uart0_qmsg->size=0;
            i = 1;
        }
        
        /*接收中断处理*/
        if(SUBSRCPND&INT_RXD0){ 

            uart0_revice_msg(uart0_qmsg);
            
            /*如果消息队列里有数据,则使能INT_TXD0中断*/
            if(uart0_qmsg->size){   
                INTSUBMSK &= ~(1<<1);
            }
            
            
            cleanIQR();
            
            return 0;        
        }

        /*发送中断处理*/
        if(SUBSRCPND&INT_TXD0){

            uart0_sent_msg(uart0_qmsg);
            
            /*关闭INT_TXD0中断使能*/
            INTSUBMSK |= (1<<1);  
            
            cleanIQR();
            
            return 0;    
        }
        
        
        /*选择了水平触发所以这里可以直接把所以中断请求清除,退出之后只要满足触发条件还是会触发中断*/
        cleanIQR();
        return 0;
    }

  • 相关阅读:
    小程序 生成二维码
    uni-app调用wifi接口
    微信小程序代码上传,审核发布小程序
    uni-app开发经验分享十五: uni-app 蓝牙打印功能
    面试题 16.11. 跳水板
    LeetCode 63. 不同路径 II
    LeetCode 44. 通配符匹配
    LeetCode 108. 将有序数组转换为二叉搜索树
    LeetCode 718. 最长重复子数组
    LeetCode 814. 二叉树剪枝
  • 原文地址:https://www.cnblogs.com/sky-heaven/p/5031785.html
Copyright © 2020-2023  润新知