裸奔程序之UART

      开发平台:ADS1.2

      实验实现功能:利用TQ2440开发板与PC机通过UART通信方式实现通信。

——————————————————————————————————————

#define GLOBAL_CLK 1
#include "def.h"
#include "2440addr.h"
#include "2440lib.h"

void CalcBusClk(void);
void Main()
{
       char string[256];

       rMPLLCON =(92<<12)|(1<<4)|1;  //设置FCLK为400M
 
      ChangeClockDivider(2,1);            //这个函数在2440lib.c中定义的,设置分频比为1:4:8
 
      CalcBusClk();                              //计算总线频率
 
      Uart_Select (0);                        //选择串口0
 
      Uart_Init (0,115200);              // 0代表使用当前的PCLK ,115200是波特率
 
      rGPHCON &=~((3<<4)|(3<<6));
      rGPHCON |=(2<<4)|(2<<6);      //把GPH3、GPH2设置为RXD[0] 、TXD[0] 功能

     Uart_Printf("\n This is an uart test,write by lwj\n"); //串口上打印

    while(1)
   {
           Uart_Printf("please,input string\n") ;    //这些函数都是在2440lib.c 中定义的
  
          Uart_GetString(string);                        //获取输入的字符
   
          Uart_Printf("you input string: %s\r\n",string);  //打印出输入的字符
   }            
}

void CalcBusClk(void)    //计算总线频率
{
       U32 val,UPLL;
       U8 m, p, s;
       val = rMPLLCON;
       m = (val >> 12) & 0xff;
       p = (val >> 4) & 0x3f;
       s = val & 3;

      FCLK = ((m+8)*(FIN/100)*2)/((p+2)*(1<<s))*100;

      val = rCLKDIVN;
      m = (val >> 1) & 3;
      p = val & 1;
      val = rCAMDIVN;
      s = val >> 8;

     switch (m)
    {
         case 0:  HCLK = FCLK;              break;
         case 1:  HCLK = FCLK >> 1;      break;
         case 2:
         if(s & 2)  HCLK = FCLK >> 3;
         else       HCLK = FCLK >> 2;      break;
         case 3:
         if(s & 1)  HCLK = FCLK / 6;
         else       HCLK = FCLK / 3;         break;
}

       if(p)
                   PCLK = HCLK >> 1;
       else
                  PCLK = HCLK;
 
      val = rUPLLCON;
       m = (val >> 12) & 0xff;
       p = (val >> 4) & 0x3f;
       s = val & 3;
       UPLL = ((m+8)*FIN)/((p+2)*(1<<s));
        UCLK = (rCLKDIVN&8)?(UPLL>>1):UPLL;
}

—————————————————————————————————————

void ChangeClockDivider(int hdivn_val,int pdivn_val)       //from  2440lib.c
{
int hdivn=2, pdivn=0;

// hdivn_val (FCLK:HCLK)ratio hdivn
// 11           1:1       (0)
// 12           1:2       (1)
// 13           1:3       (3)
// 14           1:4       (2)
// pdivn_val (HCLK:PCLK)ratio pdivn
// 11           1:1       (0)
// 12           1:2       (1)
switch(hdivn_val) {
  case 11: hdivn=0; break;
  case 12: hdivn=1; break;
  case 13:
  case 16: hdivn=3; break;
  case 14:
  case 18: hdivn=2; break;
}

switch(pdivn_val) {
  case 11: pdivn=0; break;
  case 12: pdivn=1; break;
}

//Uart_Printf("Clock division change [hdiv:%x, pdiv:%x]\n", hdivn, pdivn);
rCLKDIVN = (hdivn<<1) | pdivn;

switch(hdivn_val) {
  case 16:  // when 1, HCLK=FCLK/8.
   rCAMDIVN = (rCAMDIVN & ~(3<<8)) | (1<<8);
  break;
  case 18:  // when 1, HCLK=FCLK/6.
   rCAMDIVN = (rCAMDIVN & ~(3<<8)) | (1<<9);
  break;
}

if(hdivn!=0)
  MMU_SetAsyncBusMode();
else
  MMU_SetFastBusMode();
}

—————————————————————————————————————

void Uart_Init(int pclk,int baud)                                                  //from 2440lib.c
{
    int i;
    if(pclk == 0)
    pclk    = PCLK;
    rUFCON0 = 0x0;   //UART channel 0 FIFO control register, FIFO disable
    rUFCON1 = 0x0;   //UART channel 1 FIFO control register, FIFO disable
    rUFCON2 = 0x0;   //UART channel 2 FIFO control register, FIFO disable
    rUMCON0 = 0x0;   //UART chaneel 0 MODEM control register, AFC disable
    rUMCON1 = 0x0;   //UART chaneel 1 MODEM control register, AFC disable
//UART0
    rULCON0 = 0x3;   //Line control register : Normal,No parity,1 stop,8 bits
     //    [10]       [9]     [8]        [7]        [6]      [5]         [4]           [3:2]        [1:0]
     // Clock Sel,  Tx Int,  Rx Int, Rx Time Out, Rx err, Loop-back, Send break,  Transmit Mode, Receive Mode
     //     0          1       0    ,     0          1        0           0     ,       01          01
     //   PCLK       Level    Pulse    Disable    Generate  Normal      Normal        Interrupt or Polling
    rUCON0  = 0x245;   // Control register
    rUBRDIV0=( (int)(pclk/16./baud+0.5) -1 );   //Baud rate divisior register 0
//UART1
    rULCON1 = 0x3;
    rUCON1  = 0x245;
    rUBRDIV1=( (int)(pclk/16./baud+0.5) -1 );
//UART2
    rULCON2 = 0x3;
    rUCON2  = 0x245;
    rUBRDIV2=( (int)(pclk/16./baud+0.5) -1 );   

    for(i=0;i<100;i++);
}

———————————————————————————————————————
       我们先从main函数开始, rMPLLCON =(92<<12)|(1<<4)|1;  //设置FCLK为400M

      首先设置MPLL提高系统时钟为400MHz,根据下面这个公式求得,令MDIV=92,PDIV=1,SDIV=1。

       MPLL = (2*m*Fin)/(p*2^s),其中m = (MDIV + 8),   p = (PDIV +2) , s = SDIV。
      ChangeClockDivider(2,1);      //这个函数在2440lib.c中定义的,设置分频比为1:4:8
      ChangeClockDivider(int hdivn_val,int pdivn_va);  设置分频的寄存器CLKDIVN的二个HDIVN,PDIVN,就是这个函数的二个int参数,其中HDIVN = 2; PDIVN = 1;并且CAMDIVN中的[8]位HCLK3_HALF = 0b ,[9]位HCLK4_HALF = 0b。
使得FCLK:HCLK:PCLK = 1:4:8。 
 
裸奔程序之UART_第1张图片
      CalcBusClk();                 //计算总线频率
      调用这个函数后,实现FCLK = 400MHz,FCLK:HCLK:PCLK = 1:4:8。 故使得PCLK = 50MHz,这个PCLK = 50MHz将走位UART的时钟源,波特率的计算将会用到这个值。
     Uart_Select (0);              //选择串口0
——————————————————————————————————————
      static int whichUart=0;                       //from 2440lib.c
      void Uart_Select(int ch)
    {
             whichUart = ch;
    }
——————————————————————————————————————
       Uart_Init (0,115200);         // 0代表使用当前的PCLK ,115200是波特率
       调用这个函数后,我们UART选用的时钟源被配置为PCLK = 1/8*FCLK =50MHz,UFCONn初始化UART通道0、1、2为非FIFO模式,UMCON0 、UMCON1初始化UART通道0、1的流控失效,ULCONn初始化UART通道0、1、2格式为,普通模式、无奇偶校验位、1个停止位、8位数据位。
 
  裸奔程序之UART_第2张图片
 
       UCONn初始化为选择PCLK作为UART时钟源,发送中断方式为电平,接收中断方式为脉冲,接收超时使能:disable,
接收错误状态中断使能:出错时产生中顿,自环模式(就是将TxDn和RxDn在内部相连,用于自发自收):正常模式,
发送模式为中断方式或查询方式,接收模式为中断方式或查询方式。
       波特率计算公式:rUBRDIV0=( (int)(pclk/16./baud+0.5) -1 );   //Baud rate divisior register 0
裸奔程序之UART_第3张图片
 
       根据上式据算出来的UBRDIVn不寄存器值不一定是整数,只要其误差在1.87%之内即可。误差计算公式如下:
裸奔程序之UART_第4张图片
       rGPHCON &=~((3<<4)|(3<<6));
      rGPHCON |=(2<<4)|(2<<6);      //把GPH3、GPH2设置为RXD[0] 、TXD[0] 功能
     我们所涉及的UART通道管脚设置为UART功能,比如UART通道0中,GPH2、GPH3分别用作TXD0、RXD0,要使用UART通道0时,先设置GPHCON寄存器将GPH2、GPH3引脚功能设置为TXD0、RXD0。
裸奔程序之UART_第5张图片
 
      Uart_Printf("\n This is  an uart test,write by lwj\n"); //串口上打印
      Uart_GetString(string);       //获取输入的字符
      这两个函数都是来自 2440lib.c这个文件。具体可以参考这个文件,这里不详述。我们要用时,相当于直接调用库函数。使用别人写好的程序,何乐而不为呢。
————————————————————————————————————
      UART的实验就讲解到这里啦。裸奔程序之UART - 23号的wj - 伟坚的博客

你可能感兴趣的:(String,input,平台)