資料通信的方式
資料通信的方式基本分為:
(1)、并行通信:多條資料線将資料的各位同屬傳送。
特點:傳輸速度快,适用于短距離通信。
(2)、串行通信:一條資料線将資料一位一位的順序傳送。
特點:線路簡單,低成本,适用于遠距離通信。
一: 異步通信:
以一個字元為傳輸機關,通信中兩個字元間的時間間隔是不固定的,然而同一個字元中的兩個相鄰位之間的時間間隔是固定的。
二: 通信協定
指雙方約定的一些規則。在異步通訊時,對資料格式有如下的約定:有空閑位,起始位,資料位,奇偶校驗位,停止位。
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIyZuBnL5IDMz8FNyETOxYTN0MTMvwlMy8CX4AjMxAjMvw1ckF2bsBXdvwFdl5mLuR2cj5Set1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
(1)、起始位:先發送一個邏輯信号“0”信号,表示傳輸字元的開始。
(2)、資料位:緊接在起始位之後。資料位的個數可以是4,5,6,7,8等,從最低位開始傳送,靠時鐘定位。
(3)、奇偶校驗位:資料位加上這一位後,使得“1”的資料位應為偶數(偶校驗)或奇數(奇校驗),以此校驗資料傳送的正确性。
(4)、停止位:他是一個字元資料的結束标志。
(5)、空閑位:處于邏輯“1”狀态,表示目前線路上沒有資料傳送。
波特率
衡量資料傳送速率的名額:記錄每秒傳送的二進制位數。
例如資料傳送速率為120字元/秒,而一個字元為10位,則其傳送的波特率為10*120=1200位/秒=1200波特。
傳送方式
UART基本原理
Universal Asynchronous Receiver Transimitter,簡稱UART,通用異步收發器,它用來串行傳輸資料。
發送時:CPU将資料并行寫入UART,UART按照一定的格式在一根信号線上串行發送;
接收時:UART檢測另一根信号線上的信号,将串行資料放在緩沖區中,CPU可讀取UART獲得的這些資料。
UART驅動程式設計
發送資料
将要發送的資料寫入UTXHn,UART會将它儲存到緩沖區中,并自動發送出去。
接收資料
當UART接收到資料時(UARTSTATn寄存器bit[0]被置1,),CPU讀取URXHn寄存器,即可獲得資料。
實驗主要代碼:
main.c
#define GLOBAL_CLK 1
#include <stdlib.h>
#include <string.h>
#include "def.h"
#include "option.h"
#include "2440addr.h"
#include "2440lib.h"
#include "2440slib.h"
#include "mmu.h"
#include "profile.h"
#include "memtest.h"
static void cal_cpu_bus_clk(void);
void Set_Clk(void);
void beep_init(void);
void beep_run(void);
void delay(int times)
{
int i,j;
for(i=0;i<times;i++)
for(j=0;j<400;j++);
}
void Main(void)
{
int i;
int Scom=0;
Set_Clk();
beep_init();
Uart_Init(0,115200); //在2440lib.c檔案中下面列出了
//序列槽通道選擇
Uart_Select(Scom);
//序列槽發送資料
for(i=0;i<10;i++)
Uart_Printf("\nHello World!\n");
}
void Set_Clk(void)
{
int i;
U8 key;
U32 mpll_val = 0 ;
i = 2 ; //don't use 100M!
//boot_params.cpu_clk.val = 3;
switch ( i ) {
case 0: //200
key = 12;
mpll_val = (92<<12)|(4<<4)|(1);
break;
case 1: //300
key = 13;
mpll_val = (67<<12)|(1<<4)|(1);
break;
case 2: //400
key = 14;
mpll_val = (92<<12)|(1<<4)|(1);
break;
case 3: //440!!!
key = 14;
mpll_val = (102<<12)|(1<<4)|(1);
break;
default:
key = 14;
mpll_val = (92<<12)|(1<<4)|(1);
break;
}
//init FCLK=400M, so change MPLL first
ChangeMPllValue((mpll_val>>12)&0xff, (mpll_val>>4)&0x3f, mpll_val&3); //set the register--rMPLLCON
ChangeClockDivider(key, 12); //the result of rCLKDIVN [0:1:0:1] 3-0 bit
cal_cpu_bus_clk(); //HCLK=100M PCLK=50M
}
static void cal_cpu_bus_clk(void)
{
static U32 cpu_freq;
static U32 UPLL;
U32 val;
U8 m, p, s;
val = rMPLLCON;
m = (val>>12)&0xff;
p = (val>>4)&0x3f;
s = val&3;
//(m+8)*FIN*2 不要超出32位數!
FCLK = ((m+8)*(FIN/100)*2)/((p+2)*(1<<s))*100; //FCLK=400M FIN=12000000
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;
if(s&0x10)
cpu_freq = HCLK;
else
cpu_freq = FCLK;
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 beep_init(void)
{
rGPBCON &= ~(0x3<<0);
rGPBCON |= (0x1<<0);
}
void beep_run(void)
{
rGPBDAT |= (0x1<<0);
delay(5000);
rGPBDAT &= (0x0<<0);
delay(5000);
}
一些main函數中調用到的函數:
2440lib.c
....................
//***************************[ UART ]******************************
static int whichUart=0;
void Uart_Init(int pclk,int baud)
{
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 1001000101
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++); //短暫延時
}
void Uart_Select(int ch)
{
whichUart = ch;
}
//=====================================================================
//If you don't use vsprintf(), the code size is reduced very much.
void Uart_Printf(char *fmt,...)
{
va_list ap;
char string[256];
va_start(ap,fmt);
vsprintf(string,fmt,ap);
Uart_SendString(string);
va_end(ap);
}
//va_start,va_end成對出現
//====================================================================
void Uart_SendString(char *pt)
{
while(*pt)
Uart_SendByte(*pt++);
}
//=====================================================================
void Uart_SendByte(int data)
{
if(whichUart==0)
{
if(data=='\n')
{
while(!(rUTRSTAT0 & 0x2));
// Delay(1); //because the slow response of hyper_terminal
WrUTXH0('\r');
}
while(!(rUTRSTAT0 & 0x2)); //Wait until THR is empty.
// Delay(1);
WrUTXH0(data);
}
else if(whichUart==1)
{
if(data=='\n')
{
while(!(rUTRSTAT1 & 0x2));
//Delay(1); //because the slow response of hyper_terminal
rUTXH1 = '\r';
}
while(!(rUTRSTAT1 & 0x2)); //Wait until THR is empty.
//Delay(1);
rUTXH1 = data;
}
else if(whichUart==2)
{
if(data=='\n')
{
while(!(rUTRSTAT2 & 0x2));
//Delay(1); //because the slow response of hyper_terminal
rUTXH2 = '\r';
}
while(!(rUTRSTAT2 & 0x2)); //Wait until THR is empty.
//Delay(1);
rUTXH2 = data;
}
}