SOC串口的配置

SOC串口的配置

1 UART工作原理

SoC共集成了12路的UART。这12路UART均可以配置为智能UART模式,由于我们的驱动是透传数据通信,所以不使用到智能模式。12路UART可以独立并行工作,每一路UART都有一个独立的FIFO,其大小为4k*8bit,发送和接收各为2k*8bit;通讯数据格式可以配置,默认是一个起始位、八位数据位、无校验、一个停止位;通讯波特率可通过软件设置,典型的波特率为38.4Kbps、76.8Kbps、115.2Kbps、614.4Kbps;最高波特率1Mbps;具有相应的通讯发送和接收的握手标志;通讯接收错误、发送FIFO变空以及接收FIFO达到阈值都会产生中断,并可通过软件查询内部的中断标志寄存器获得中断源信息;可以和通用的异步串行通讯控制器进行正常的通讯。其体系结构如图1所示。

 

图1 UART体系结构

数据接收先通过缓存FIFO,然后进入到接收链路,进行滤波后送入到控制器,数据发送通过发送链路到发送缓存FIFO,信号输出。

2 配置流程

Soc的UART支持非智能模式和智能模式,我们使用非智能模式,其配置流程如下:

  1. 配置UART的时钟使能,配置外设时钟使能寄存器(0x40C00000)的15-4bit为0xfff,使能12路串口时钟。
  2. 配置UART的时钟源选择,配置外设配置寄存器(0x40C00004)的第4位为1,选择UART模块时钟为AHB模块主时钟.
  3. 配置串口引脚复用寄存器IOMUX的3-0bit为0x0,配置为UART串口引脚功能。
  4. 复位UART功能,向UART串口命令寄存器CMD中写入0xff,并且进行延时等待复位完成。
  5. 配置UART的波特率,,先分析PLL主时钟的设置数值,如果是旁路时钟的话,通过外设时钟直接计算波特率数值,如果是锁相环时钟的话,通过主时钟的数值计算波特率数值,其波特率数值计算公式为:(PERIPHERAL_CLK/(16*BaudRate)) & 0xff;PERIPHERAL_CLK表示串口外设时钟,旁路为50MHz,主时钟模式为主时钟的1/2。
  6. 配置UART为非智能模式,1个停止位,偶校验,FIFO模式,正常工作模式,并且使能接收功能,配置通用控制寄存器UCR(0bit为0x0,3-1为0x0,8bit为0x0,9bit为0,10bit为1,11bit为0)。
  7. 如果使用中断,配置FIFO阈值寄存器ITL,范围是1-2048。
  8. 如果使用中断,配置串口中断使能寄存器IER,配置1bit为1使能达到阈值触发中断。
  9. 如果使用中断,中断服务函数中读取中断标志寄存器清除中断标识。
  10. 如果使用中断,配置对应中断ID(uart0-uart11为62-73)号对应的中断分配器寄存器和CPU中断接口控制器寄存器。
  11. 串口发送函数的设计,轮询获取UART状态寄存器的数值,如果串口发送FIFO满了就不写数据到发送FIFO中,如果发送FIFO不满则将数据写入到发送FIFO中。
  12. 串口接收函数的设计,轮询获取UART状态寄存器的数值,如果串口接收FIFO不空就将接收FIFO中所有的数据全部读出给用户,如果接收FIFO空了,就不读数据给用户。

3 数据结构封装

根据UART模块寄存器地址在内存分配图中的分布,将其地址定义为整型宏定义,将寄存器定义为各位各个功能位域的结构联合体。这样子将整型地址转换成寄存器的结构联合体指针,就能够通过寄存器位域去编写底层驱动了,图1表示宏定义寄存器的定义和类型转换,图2表示寄存器结构联合体定义。

 

 

图1

 

 

 

图2

附录:源码

soc_uart.h头文件:

/*
 * soc_uart.h
 *
 *  Created on: 2020年5月25日
 *      Author: dz
 */

#ifndef COMMON_SOC_UART_H_
#define COMMON_SOC_UART_H_

#include "soc.h"
/*-------------------------校验模式----------------------------*/
typedef enum
{
    even_parity             = 0,    //接收发送均为偶校验
    odd_parity                 = 1,    //接收发送均为奇校验
    txeven_rxodd_parity     = 2,     //发送偶校验,接收奇校验
    txodd_rxeven_parity     = 3,    //发送奇校验,接收偶校验
    txeven_rxnone_parity     = 4,     //发送偶校验,接收无校验
    txodd_rxnone_parity     = 5,    //发送奇校验,接收无校验
    none_parity             = 6,     //不产生校验
} UART_PARITY_TYPE;

/*-------------------------停止位个数----------------------------*/
typedef enum
{
    one_stop         = 0,    //1位停止位
    two_stop         = 1,    //2位停止位
} UART_STOP_TYPE;


typedef struct _Uart_Config_Type{
    Uint32 BaudRate;
    UART_STOP_TYPE stop;                    //停止位个数
    UART_PARITY_TYPE parity;                 //奇偶校验模式
    BOOL isLoop;                //是否自环模式
    BOOL isIntelligenceMode;     //是否智能工作模式
    BOOL isEnableReceived;        //是否使能接收
    BOOL isRamMode;                //是否使用RAM模式
}Uart_Config_Type;

Uint32 FIND_UART(Uint8 Numb,REG_UART_TYPE** UARTx);

Uint32 UART_GetFlagStatus(Uint8 Numb,UCRUSR_REG *ucr_value);

Uint32 UART_SendData(Uint8 Numb, Uint8* buff, Uint32 length);

Uint32 UART_ReceiveData(Uint8 Numb, Uint8* buff, Uint32* length);

void UART_Init(Uint8 Numb,Uint32 BaudRate,Uint32 parity);

void UART_INT_Enable(Uint8 Numb, Uint32 type);

Uint8 UART_Get_IntStatus(Uint8 Numb);
#endif /* COMMON_SOC_UART_H_ */
 

soc_uart.c驱动源文件:

/*
 * soc_uart.c
 *
 *  Created on: 2020年5月25日
 *      Author: dz
 */

#include "soc_uart.h"

Uint32 FIND_UART(Uint8 Numb,REG_UART_TYPE** UARTx)
{
    if(Numb > 11)
    {
        return 2;
    }
    switch(Numb)
    {
        case 0:
        {
            *UARTx = REG_UART0;
        }break;
        case 1:
        {
            *UARTx = REG_UART1;
        }break;
        case 2:
        {
            *UARTx = REG_UART2;
        }break;
        case 3:
        {
            *UARTx = REG_UART3;
        }break;
        case 4:
        {
            *UARTx = REG_UART4;
        }break;
        case 5:
        {
            *UARTx = REG_UART5;
        }break;
        case 6:
        {
            *UARTx = REG_UART6;
        }break;
        case 7:
        {
            *UARTx = REG_UART7;
        }break;
        case 8:
        {
            *UARTx = REG_UART8;
        }break;
        case 9:
        {
            *UARTx = REG_UART9;
        }break;
        case 10:
        {
            *UARTx = REG_UART10;
        }break;
        case 11:
        {
            *UARTx = REG_UART11;
        }break;
        default:
        {
            *UARTx = REG_UART0;
        }
        break;
    }
    return 0;
}

Uint32 UART_GetFlagStatus(Uint8 Numb,UCRUSR_REG *ucr_value)
{
    REG_UART_TYPE* Uart;
    Uint32 rel = 0;
    rel = FIND_UART(Numb,&Uart);
    if(rel == 0)
    {
        ucr_value->all = Uart->UCR.all;
    }
    else
    {
        return rel;
    }
    return 0;
}

Uint32 UART_SendData(Uint8 Numb, Uint8* buff, Uint32 length)
{
    Uint32 i = 0;
    Uint32 Flag_Full = 0;
    REG_UART_TYPE* Uart;
    Uint32 rel = 0;
    UCRUSR_REG ucr_reg;

    if((length<1)||(length>255))
        return 4;

    rel = FIND_UART(Numb,&Uart);
    if(rel == 0)
    {
        do
        {
            UART_GetFlagStatus(Numb,&ucr_reg);
            Flag_Full = ucr_reg.bit1.FIFOTF;
            if(1 == Flag_Full)
            {
                return 5;
            }
            else
            {
                Uart->FIFO = *(buff+i);
                i = i + 1;
            }
        }while(i < length);
    }
    else
    {
        return rel;
    }
    return 0;
}

Uint32 UART_ReceiveData(Uint8 Numb, Uint8* buff, Uint32* length)
{
    Uint32 rel = 0;
    REG_UART_TYPE* Uart;
    UCRUSR_REG ucr_reg;
    Uint32 Length_Tmp = 0;
    Uint32 Flag_Empty = 1;
    Uint32 Flag_Error = 0;

    rel = FIND_UART(Numb,&Uart);
    if(rel == 0)
    {
       do
       {
            UART_GetFlagStatus(Numb,&ucr_reg);
            Flag_Empty = ucr_reg.bit1.FIFORE;
            Flag_Error |= ucr_reg.bit1.PE;
            if(0 == Flag_Empty)
            {
                *(buff + Length_Tmp) = Uart->FIFO;
                Length_Tmp = Length_Tmp + 1;
            }
       }while((Length_Tmp < 255) && (0 == Flag_Empty));

       *length = Length_Tmp;

       if(0 == Length_Tmp)
       {
            return 6;
       }

       if(1 == Flag_Error)
       {
           return 9;
       }
    }
    else
    {
        return rel;
    }
    return 0;
}

void delay(int count)
{
    while(count--);
}

void UART_Init(Uint8 Numb,Uint32 BaudRate,Uint32 parity)
{
    REG_UART_TYPE* Uart;
    Uint32 rel = 0;
    Uint32 bypass, fbdiv, refdiv, PERIPHERAL_CLK,main_clk_temp;
    Uart_Config_Type Uart_Config_Value;
    Uart_Config_Value.BaudRate = BaudRate;
    Uart_Config_Value.isEnableReceived = true;
    Uart_Config_Value.isIntelligenceMode = flase;
    Uart_Config_Value.isLoop = flase;
    Uart_Config_Value.isRamMode = flase;
    if(parity == 2)
    {
        Uart_Config_Value.parity = even_parity;
    }
    else if(parity == 3)
    {
        Uart_Config_Value.parity = odd_parity;
    }
    else
    {
        Uart_Config_Value.parity = none_parity;
    }
    Uart_Config_Value.stop = one_stop;
    rel = FIND_UART(Numb,&Uart);
    if(rel == 0)
    {
        //1,选择UART时钟源
        BASE_AHB->PeriphConfig.bit.UARTCLKSEL = 0x1;
        //2,配置UART时钟使能
        BASE_AHB->PeriphClken.bit.UART = 0xfff;
        //3,配置管脚复用
        UART_IOMUX->bit.UART01 = 0X0;
        UART_IOMUX->bit.UART23 = 0X0;
        UART_IOMUX->bit.UART45 = 0X0;
        UART_IOMUX->bit.UART67 = 0X0;
        //4,复位uart
        Uart->CMD = 0xff;
        delay(0x100);
        //5,配置波特率
        //解析PLL主时钟寄存器数值
        bypass = BASE_AHB->PllMain.bit.BYPASS;
        fbdiv = BASE_AHB->PllMain.bit.FBDIV;
        refdiv = BASE_AHB->PllMain.bit.REFDIV;
        if(bypass == 1)
        {
            PERIPHERAL_CLK = 50000000;
            Uart->BRSR = (PERIPHERAL_CLK/(16*(Uart_Config_Value.BaudRate))) & 0xff;
        }
        else
        {
            main_clk_temp = (fbdiv/refdiv) *(50000000/2);                         //计算系统主时钟
            PERIPHERAL_CLK = main_clk_temp/2;                                     //AHB挂载的外设时钟为系统主时钟的一半
            Uart->BRSR = (PERIPHERAL_CLK/(16*(Uart_Config_Value.BaudRate))) & 0xff;    // BRSR<=0xff
        }
        //6,配置非智能模式,1个停止位,偶校验,FIFO模式,正常模式,使能接收
        Uart->UCR.bit0.MODE = Uart_Config_Value.isIntelligenceMode;
        Uart->UCR.bit0.STOPBITS = Uart_Config_Value.stop;
        Uart->UCR.bit0.PAR = Uart_Config_Value.parity;
        Uart->UCR.bit0.FIFO = Uart_Config_Value.isRamMode;
        Uart->UCR.bit0.LOOP = Uart_Config_Value.isLoop;
        Uart->UCR.bit0.RXEN = Uart_Config_Value.isEnableReceived;
        //7,配置FIFO阈值
        Uart->ITL = 200;
    }
    else
    {
        return;
    }
}

void UART_INT_Enable(Uint8 Numb, Uint32 type)
{
    REG_UART_TYPE* Uart;
    Uint32 rel = 0;
    rel = FIND_UART(Numb,&Uart);
    if(rel == 0)
    {
        Uart->IER.all = type;
    }
    else
    {
        return;
    }
}

Uint8 UART_Get_IntStatus(Uint8 Numb)
{
    REG_UART_TYPE* Uart;
    Uint32 rel = 0;
    Uint8 status = 0;
    rel = FIND_UART(Numb,&Uart);
    if(rel == 0)
    {
        status = Uart->IFR.bit.RECVC;
    }
    else
    {
        return -1;
    }
    return status;

}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值