先說明一下爲什麼做了點燈我就做串口了,原因是我覺得串口調試通了在做以後的會更加容易,因爲有些東西可以通過串口進行打印出來,這樣就可以看到自己那裏出錯了,對於LED程序當然是第一需要做的。因爲在中斷中是不允許進行打印輸出的,所以到時候調試中斷就需要用點燈的方式來進行調試。
因此整個流程的實現:先搭建開發環境---------->再進行一些初始程序的編寫(LED與Uart便於以後調試)------------>各個模塊的裸機程序的編寫---------------------->以一個小型項目的形式把所用到的模塊都結合起來。
串口的編寫:
最最要注意的就是時鐘的配置,由於這個問題在我做串口的過程中糾結的時間真的很長,而且沒有使用示波器,問題真的有點難找。可以看看這篇文章提到的東西
一、配置時鐘
在配置串口的時候要注意時鐘配置,如果不想自己進行配置,想用系統默認的配置,可以在初始化代碼中進行查詢,因爲如果沒有弄清楚時鐘頻率,後面對於波特率的配置肯定不能夠實現。寄存器的使用在上一篇文章中已經介紹,這裏就直接貼出我自己的時鐘配置代碼
//時鐘的配置
void CLK_Configure(void)
{
rMPLLCON = 0;
//MDIV = 0x38; PDIV = 0x2; SDIV = 0x2;
//outfrequency = 48MHz;
rMPLLCON |= (0x38<<12)|(0x2<<4)|(0x3);
//HCLK = FCLK, PCLK = HCLK/2
//FCLK = HCLK = 48M PCLK = 24M;
rCLKDIVN = 0;
rCLKDIVN |=0x1;
}
二、對串口0進行一些初始化操作
對於我的硬件平臺MINI2440中,串口使用了GPH這個I/O,因此需要配置GPHCON控制寄存器,把對應的端口配置成爲串口功能,這個控制寄存器簡單,就不多介紹。
ULCON0 :串口線性控制寄存器,
ULCON0 [1,0]——數據位數(5,6,7,8)位
ULCON0 [2]——停止位數(1,2)位
ULCON0 [5:3]——奇偶校驗(奇校驗,偶校驗,不校驗,強制校驗)
ULCON0 [6]——普通模式還是紅外模式
UCON0:串口控制寄存器,相關可以控制的有以下一些
接收與發送的模式(禁止,中斷和流模式,DMA模式)
自環檢測模式,檢驗到錯誤後,是否發生中斷,接收與發送如果是發送模式時,中斷信號請求類型,是脈衝還是低電平,以及時鐘的選擇,對照datasheet可以一步一步配置出來。
UFCON0:是對UART中的FIFO(先進先出緩衝區)的配置,主要是避免串口要傳輸的數據太多過分頻繁中斷CPU導致CPU效率太低的一個緩衝功能,在我們的程序中,沒有使用,一般也不用使用,我認爲如果數據量太多可以通過以太網,或者其他方式進行,不需要通過UART進行。如果想深入瞭解請參看
http://hi.baidu.com/611bob/item/7d14e3312e70dab3623aff24
具體Uart初始化代碼如下
//Uart0的初始化配置
void My_Uart_Init(void)
{
//GPH0-3配置爲Uart功能
rGPHCON &= ~(0xFF);
rGPHCON |= (1<<1)|(1<<3)|(1<<5)|(1<<7);
//正常傳輸,奇偶校驗,一位停止位,八位數據位
rULCON0 |= 0x3;
//默認配置,無中斷,無DMA,時鐘爲PCLK
rUCON0 |= (1<<2)|(1);
rUFCON0 = 0;//FIFO緩衝不使用
}
波特率配置
計算公式如下
UBRDIVn = (int)(UART clock/(baud rate * 16))-1;
因此在配置好時鐘頻後,根據自己想要的波特率計算出UBRDIVn的值即可完成配置
代碼如下:
//波特率的設置
void Set_Baud(unsigned int baud)
{
rUBRDIV0 = ((int)(24000000/(baud*16))-1);
}
下面是在程序中幾個簡單的封裝函數,包括單個字符發送,字符串發送,以及接收字符與字符串。
//單個字符的發送
void My_Uart_Send(unsigned char letter)
{
while(!(rUTRSTAT0&0x02)); //等待發送緩存空
rUTXH0 = letter;
}
//字符串的發送
void My_Uart_SendString(unsigned char* str)
{
unsigned char *temp;
temp = str;
while('\0'!=*temp)
{
My_Uart_Send(*temp);
temp++;
}
}
//從終端使用Uart0進行字符的接收
unsigned char My_Uart_Receive(void)
{
while(!(rUTRSTAT0&0x01)); //等待接收緩存滿
return rURXH0;
}
//從終端接收一串字符,沒有考慮刪除等特殊處理
void My_Uart_GetString(unsigned char *str)
{
unsigned char letter;
while('\r'!=(letter=My_Uart_Receive()))
{
*str = letter;
str++;
My_Uart_Send(letter);
}
*str='\0';
My_Uart_Send('\n');
}