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

1.相关原理图

 八、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

八、mini2440裸机程序之UART(2)UART0与PC串口通信_第2张图片

注:

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

 

 八、mini2440裸机程序之UART(2)UART0与PC串口通信_第3张图片

注:

脉冲触发:指的是在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-bytePC机上发一个字节触发中断,在接收中断里接收一个字节,延迟3秒,在这段时间里再发1个字节,这样会有一个从empty1-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

八、mini2440裸机程序之UART(2)UART0与PC串口通信_第4张图片

注:

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

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

UCON0  = 0x305

 

③UFCON0

八、mini2440裸机程序之UART(2)UART0与PC串口通信_第5张图片

注:

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

八、mini2440裸机程序之UART(2)UART0与PC串口通信_第6张图片

注:

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

八、mini2440裸机程序之UART(2)UART0与PC串口通信_第7张图片

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

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

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

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

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

 

⑦UFSTAT0

八、mini2440裸机程序之UART(2)UART0与PC串口通信_第8张图片

注:

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

Tx FIFO count :Tx FIFO里的data数。

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

Rx FIFO count :Rx FIFO里的data数。

 

⑧UMSTAT0

八、mini2440裸机程序之UART(2)UART0与PC串口通信_第9张图片

注:

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

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

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

 

 

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

八、mini2440裸机程序之UART(2)UART0与PC串口通信_第10张图片

注:

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

 

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


注:

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

RXDATA:存放接收到的数据

 

 

3.流程图设计

 

    ①主流程图

                                                                        八、mini2440裸机程序之UART(2)UART0与PC串口通信_第11张图片

    ②中断处理子程序

                                                                              

    ③中断服务子函数

                                              八、mini2440裸机程序之UART(2)UART0与PC串口通信_第12张图片

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;
}






你可能感兴趣的:(八、mini2440裸机程序之UART(2)UART0与PC串口通信)