自己动手写的UART2驱动

    昨天发现新唐的BSP中没有提供UART2的定义 即其操作,只定义了UART0和UART1及其驱动操作。但是涉及的板子中又弄了3路串口,当然UART2在其中。
      第一反应就是查阅新唐的资料,NUC1**的前期设计文档中,有些说可以支持UART2,但是又有很多定义的地方都Reserve了,就是本该UART2相关的位却为保留位。心里没谱。
     没谱也没办法,咬咬牙开始吧。
     查看BSP有关定义,在DrvUART.h和 DrvUART.c中只 #define了UART0 和UART1,以及DrvGPIO.c中的DRVGPIO_FUNC中也制定一乐FUNC_UART0, 和FUNC_UART1,根本不见FUNC_UART2的踪影。可是在新唐的网站上关于NUC100RE3AN又是有3路串口的(这一点是坚定我信心的!!)
     因此萌生自己写关于UART2的驱动的决心。项目只要求往外发,所以暂时只实现这部分功能,对于接收先不予以处理(接收要麻烦些)。
     1、在串口初始化中先要DrvGPIO_InitFunction()对象应的管脚使能,FUNC_UART2对应的管脚是和FUNC_CAN1管脚复用的(都是GPD14、15)。所以
       #define FUNC_UART2 FUNC_CAN1
      这样直接DrvGPIO_InitFunction(FUNC_UART2),就将相应UART2的PIN脚使能为RX2、TX2了。
      2、然后要对UART进行配置,UART0和1是调用DrvUART_Open(UART_PORT1,(STR_UART_T)¶m);
     开始编写自己的UART2驱动文件 my_uart2.h 和my_uart2.c。
    (1) 关键之处在于UART2的基地址,查看Datasheet, 
         
    #define MY_APB2_BASE           ((     uint32_t)0x40100000)
     #define MY_UART2_BASE                (MY_APB2_BASE + 0x54000)

      (2)将原先关于UART2的结构体中的保留位改写为UART2相关位。

typedef struct
{
    __IO uint32_t  WDG_EN:1;
    __IO uint32_t  RTC_EN:1;
    __IO uint32_t  TMR0_EN:1;
    __IO uint32_t  TMR1_EN:1;
    __IO uint32_t  TMR2_EN:1;
    __IO uint32_t  TMR3_EN:1;
    __I  uint32_t  RESERVE0:2;
    __IO uint32_t  I2C0_EN:1;
    __IO uint32_t  I2C1_EN:1;
    __I  uint32_t  RESERVE1:2;
    __IO uint32_t  SPI0_EN:1;
    __IO uint32_t  SPI1_EN:1;
    __IO uint32_t  SPI2_EN:1;
    __IO uint32_t  SPI3_EN:1;
    __IO uint32_t  UART0_EN:1;
    __IO uint32_t  UART1_EN:1;
//   __I  uint32_t  RESERVE2:2;
     __IO uint32_t  UART2_EN:1;
    __I     uint32_t  RESERVE2:1;
    __IO uint32_t  PWM01_EN:1;
    __IO uint32_t  PWM23_EN:1;
    __I  uint32_t  RESERVE3:2;
    __IO uint32_t  CAN0_EN:1;
    __IO uint32_t  CAN1_EN:1;
    __I  uint32_t  RESERVE4:1;
    __IO uint32_t  USBD_EN:1;
    __IO uint32_t  ADC_EN:1;
    __I  uint32_t  RESERVE5:1;
    __IO uint32_t  ACMP_EN:1;
    __IO uint32_t  PS2_EN:1;
} MY_SYSCLK_APBCLK_T;
typedef struct
{
    SYSCLK_PWRCON_T    PWRCON;
    SYSCLK_AHBCLK_T    AHBCLK;
    MY_SYSCLK_APBCLK_T    APBCLK;
    uint32_t           RESERVED0;
    SYSCLK_CLKSEL0_T   CLKSEL0;
    SYSCLK_CLKSEL1_T   CLKSEL1;
    SYSCLK_CLKDIV_T    CLKDIV;
    uint32_t           RESERVED1;
    SYSCLK_PLLCON_T    PLLCON;
} MY_SYSCLK_T;

#define MY_SYSCLK              ((MY_SYSCLK_T *) SYSCLK_BASE)

    (3)实现打开以及 发送字符串函数

int32_t My_DrvUART_Open(UART_PORT port, STR_UART_T *sParam);
void SendChar_To_UART2(int ch);
void Send_String_To_UART2(char * str);

 

以下是直接可用的代码:my_uart2.h

#ifndef _UART2_H #define _UART2_H #include "NUC1xx.h" #include "Driver/DrvUART.h" #include "Driver/DrvSYS.h" typedef struct { __IO uint32_t WDG_EN:1; __IO uint32_t RTC_EN:1; __IO uint32_t TMR0_EN:1; __IO uint32_t TMR1_EN:1; __IO uint32_t TMR2_EN:1; __IO uint32_t TMR3_EN:1; __I uint32_t RESERVE0:2; __IO uint32_t I2C0_EN:1; __IO uint32_t I2C1_EN:1; __I uint32_t RESERVE1:2; __IO uint32_t SPI0_EN:1; __IO uint32_t SPI1_EN:1; __IO uint32_t SPI2_EN:1; __IO uint32_t SPI3_EN:1; __IO uint32_t UART0_EN:1; __IO uint32_t UART1_EN:1; // __I uint32_t RESERVE2:2; __IO uint32_t UART2_EN:1; __I uint32_t RESERVE2:1; __IO uint32_t PWM01_EN:1; __IO uint32_t PWM23_EN:1; __I uint32_t RESERVE3:2; __IO uint32_t CAN0_EN:1; __IO uint32_t CAN1_EN:1; __I uint32_t RESERVE4:1; __IO uint32_t USBD_EN:1; __IO uint32_t ADC_EN:1; __I uint32_t RESERVE5:1; __IO uint32_t ACMP_EN:1; __IO uint32_t PS2_EN:1; } MY_SYSCLK_APBCLK_T; typedef struct { SYSCLK_PWRCON_T PWRCON; SYSCLK_AHBCLK_T AHBCLK; MY_SYSCLK_APBCLK_T APBCLK; uint32_t RESERVED0; SYSCLK_CLKSEL0_T CLKSEL0; SYSCLK_CLKSEL1_T CLKSEL1; SYSCLK_CLKDIV_T CLKDIV; uint32_t RESERVED1; SYSCLK_PLLCON_T PLLCON; } MY_SYSCLK_T; #define MY_SYSCLK ((MY_SYSCLK_T *) SYSCLK_BASE) #define MY_APB2_BASE (( uint32_t)0x40100000) #define MY_UART2_BASE (MY_APB2_BASE + 0x54000) #define MY_UART2 ((UART_T *) MY_UART2_BASE) static PFN_DRVUART_CALLBACK *g_pfnUART2callback = NULL; int32_t My_DrvUART_Open(UART_PORT port, STR_UART_T *sParam); void SendChar_To_UART2(int ch); void Send_String_To_UART2(char * str); #endif

 

my_uart.c

#include <stdio.h> #include <string.h> #include "my_uart2.h" /*---------------------------------------------------------------------------------------------------------*/ /* Function: BaudRateCalculator */ /* */ /* Parameter: */ /* clk -[in] Uart Source Clock */ /* baudRate -[in] User seting BaudRate */ /* UART_BAUD_T *baud -[in] Get User Settings */ /* Returns: */ /* None */ /* Description: */ /* The function is used to get compute Baud Setting Value */ /*---------------------------------------------------------------------------------------------------------*/ static void MyBaudRateCalculator(uint32_t clk, uint32_t baudRate, UART_BAUD_T *baud) { int32_t tmp; int32_t div; if(((clk / baudRate)%16)<3) /* Source Clock mod 16 <3 => Using Divider X =16 */ { baud->DIVX_EN = 0; baud->DIVX1 = 0; tmp = clk / baudRate/16 -2; } else /* Source Clock mod 16 >3 => Up 5% Error BaudRate */ { baud->DIVX_EN = 1; /* Try to Set Divider X = 1 */ baud->DIVX1 = 1; tmp = clk / baudRate -2; if(tmp > 0xFFFF) /* If Divider > Range */ { baud->DIVX_EN = 1; /* Try to Set Divider X up 10 */ for(div = 8; div <16;div++) { if(((clk / baudRate)%(div+1))<3) { baud->DIVX1 = div; tmp = clk / baudRate / (div+1) -2; break; } } } } baud->DIV = tmp; } /*---------------------------------------------------------------------------------------------------------*/ /* Function: GetUartCLk */ /* */ /* Parameter: */ /* clk -[in] Uart Source Clock */ /* baudRate -[in] User seting BaudRate */ /* UART_BAUD_T *baud -[in] Get User Settings */ /* Returns: */ /* Current Uart Clock */ /* Description: */ /* The function is used to get Uart clock */ /*---------------------------------------------------------------------------------------------------------*/ static uint32_t MyGetUartCLk(void) { uint32_t clk =0 , div; /* Check UART Clock Source Setting */ if(SYSCLK->CLKSEL1.UART_S == 0) { clk = DrvSYS_GetEXTClock() * 1000; /* Get External Clock From DrvSYS Setting */ } else if(SYSCLK->CLKSEL1.UART_S == 1) { div = SYSCLK->CLKDIV.UART_N; /* According PLL Clock and UART_Divider to get clock */ clk = DrvSYS_GetPLLClock() * 1000 / (div+1); } else clk = 22000000; /* Clock 22Mhz */ return clk; } /*---------------------------------------------------------------------------------------------------------*/ /* Function: My_DrvUART_Open */ /* */ /* Parameter: */ /* Port -[in] UART Channel: UART_PORT2 */ /* sParam -[in] the struct parameter to configure UART */ /* include of */ /* * u32BaudRate - Baud rate */ /* * u8cParity - DRVUART_PARITY_NONE / DRVUART_PARITY_EVEN / DRVUART_PARITY_ODD*/ /* * u8cDataBits - DRVUART_DATA_BITS_5 / DRVUART_DATA_BITS_6 */ /* DRVUART_DATA_BITS_7 / DRVUART_DATA_BITS_8 */ /* * u8cStopBits - DRVUART_STOPBITS_1 / STOPBITS_1_5 / STOPBITS_2 */ /* * u8cRxTriggerLevel - LEVEL_1_BYTE to LEVEL_62_BYTES */ /* * u8TimeOut - Time out value */ /* */ /* */ /* Returns: */ /* E_DRVUART_ERR_PORT_INVALID */ /* E_DRVUART_ERR_PARITY_INVALID */ /* E_DRVUART_ERR_DATA_BITS_INVALID */ /* E_DRVUART_ERR_STOP_BITS_INVALID */ /* E_DRVUART_ERR_TRIGGERLEVEL_INVALID */ /* E_DRVUART_ERR_ALLOC_MEMORY_FAIL */ /* E_SUCCESS */ /* */ /* Description: */ /* The function is used to initialize UART */ /*---------------------------------------------------------------------------------------------------------*/ int32_t My_DrvUART_Open(UART_PORT port, STR_UART_T *sParam) { /*-----------------------------------------------------------------------------------------------------*/ /* Check UART port */ /*-----------------------------------------------------------------------------------------------------*/ if ((port != UART_PORT2)) { return E_DRVUART_ERR_PORT_INVALID; } /*-----------------------------------------------------------------------------------------------------*/ /* Check the supplied parity */ /*-----------------------------------------------------------------------------------------------------*/ if ((sParam->u8cParity != DRVUART_PARITY_NONE) && (sParam->u8cParity != DRVUART_PARITY_EVEN) && (sParam->u8cParity != DRVUART_PARITY_ODD) && (sParam->u8cParity != DRVUART_PARITY_MARK) && (sParam->u8cParity != DRVUART_PARITY_SPACE)) { return E_DRVUART_ERR_PARITY_INVALID; } /*-----------------------------------------------------------------------------------------------------*/ /* Check the supplied number of data bits */ /*-----------------------------------------------------------------------------------------------------*/ else if ((sParam->u8cDataBits != DRVUART_DATABITS_5) && (sParam->u8cDataBits != DRVUART_DATABITS_6) && (sParam->u8cDataBits != DRVUART_DATABITS_7) && (sParam->u8cDataBits != DRVUART_DATABITS_8)) { return E_DRVUART_ERR_DATA_BITS_INVALID; } /*-----------------------------------------------------------------------------------------------------*/ /* Check the supplied number of stop bits */ /*-----------------------------------------------------------------------------------------------------*/ else if ((sParam->u8cStopBits != DRVUART_STOPBITS_1) && (sParam->u8cStopBits != DRVUART_STOPBITS_2) && (sParam->u8cStopBits != DRVUART_STOPBITS_1_5) ) { return E_DRVUART_ERR_STOP_BITS_INVALID; } /*-----------------------------------------------------------------------------------------------------*/ /* Check the supplied nember of trigger level bytes */ /*-----------------------------------------------------------------------------------------------------*/ else if ((sParam->u8cRxTriggerLevel != DRVUART_FIFO_1BYTES) && (sParam->u8cRxTriggerLevel != DRVUART_FIFO_4BYTES) && (sParam->u8cRxTriggerLevel != DRVUART_FIFO_8BYTES) && (sParam->u8cRxTriggerLevel != DRVUART_FIFO_14BYTES) && (sParam->u8cRxTriggerLevel != DRVUART_FIFO_30BYTES) && (sParam->u8cRxTriggerLevel != DRVUART_FIFO_46BYTES) && (sParam->u8cRxTriggerLevel != DRVUART_FIFO_62BYTES)) { return E_DRVUART_ERR_TRIGGERLEVEL_INVALID; } /* Reset IP */ /* SYS->IPRSTC2.CAN1_RST = 1; SYS->IPRSTC2.CAN1_RST = 0; */ /* Enable UART clock */ MY_SYSCLK->APBCLK.UART2_EN = 1; /* Select UART clock source */ MY_SYSCLK->CLKSEL1.UART_S = 0; SYSCLK->PWRCON.XTL12M_EN = 1; /* Select UART clock source */ SYSCLK->CLKSEL1.CAN_S = 0; MY_UART2->FCR.TFR=1; MY_UART2->FCR.RFR=1; /* Set Rx Trigger Level */ MY_UART2->FCR.RFITL = sParam->u8cRxTriggerLevel; /* Set Parity & Data bits & Stop bits */ MY_UART2->LCR.PBE =sParam->u8cParity ; MY_UART2->LCR.WLS =sParam->u8cDataBits; MY_UART2->LCR.NSB =sParam->u8cStopBits; /* Set Time-Out */ MY_UART2->TOR =sParam->u8TimeOut; /* Set BaudRate */ MyBaudRateCalculator(MyGetUartCLk(), sParam->u32BaudRate, &MY_UART2->BAUD); return E_SUCCESS; } void SendChar_To_UART2(int ch) { while(MY_UART2->FSR.TX_FULL == 1); MY_UART2->DATA = ch; if(ch == '/n') { while(UART1->FSR.TX_FULL == 1); MY_UART2->DATA = '/r'; } } void Send_String_To_UART2(char * str) { char ch; int32_t len; int32_t i; len=strlen(str); for(i=0;i<len;i++) { ch=str[i]; SendChar_To_UART2(ch); } }

 

这是运行结果:

 

自己动手写的UART2驱动_第1张图片

你可能感兴趣的:(IO,struct,function,String,callback,div)