|
本程序是《MSP430系列單片機系統工程設計與實踐》書里面的源碼,(包含工程文件(例4.1.6) )完整例程下載:http://www.zg4o1577.cn/bbs/dpj-46245-1.html

關于本程序的詳細解說大家可以點擊上圖下載電子書
這個串口庫文件的調用方法可先下載完整代碼然后找到(例4.1.6)這一節,里面有調用方法
uart.c :
- /*
-
- MSP430F4XX單片機串口通訊程序庫(精簡版)
- 說明:該程序庫包括串口初始化、串口單字節收/發函數,以及串口終端設備接口
- 函數。可以作為各種程序的底層驅動使用。
- 要使用該庫函數,需要將本文件(UART.c)添加進工程,并在需要調用
- 串口函數的文件開頭處包含"UART.h"
- 本程序庫中的串口初始化函數會根據波特率為串口收發模塊自動選擇最
- 合適的時鐘源,自動配置波特率分頻系數,用戶不需要了解串口底層寄存器。
- 對于4800bps及以下的波特率,會選擇ACLK作為時鐘;對于4800bps以上設置,
- 會選擇SMCLK作時鐘。若串口一直打開,為了降低功耗,盡量使用4800以下波
- 特率;若使用4800以上波特率,推薦間歇使用串口。使用38400bps以上波特率
- 最好適當提高CPU主頻(2~4MHz)。
- 串口收發的等待過程中會將CPU置于休眠模式(LPM0或LPM3),以降低耗電。
- 但要注意某些應用中可能不允許關閉時鐘(比如TimerA用SMCLK作時鐘,若串
- 口等待過程中進入LPM3,關閉了SMCLK,造成計時錯誤),遇到這類情況請修
- 改UART_LPM()函數,刪除休眠語句或降低休眠深度,但功耗會有所增加。
- 程序后半部分是標準終端輸入輸出函數,對標準終端設備輸入的數據流進
- 行解析。通過串口與PC機相連;在PC機運行超級終端程序,從而將PC的屏幕和鍵
- 盤映射成單片機的輸入/輸出終端。這樣在單片機程序中可以使用格式化輸入/
- 輸出函數,如printf/scanf等。詳細的原理請參考《超級終端人機對話范例》
- 程序。終端輸入函數帶有退格功能,因此有輸入緩沖區。請根據需要自行修改
- 輸入行緩沖區大小(LINE_LENGTH),該值限定了終端設備每行最大能輸入的字符數。
-
- (C)西安電子科技大學 測控技術與儀器教研中心 編寫:謝楷 2008/02/21
-
- */
- //******************************************************************************
- //
- //
- // MSP430FE425
- // +-----------------+
- // /|\| XIN|-
- // | | | 32kHz
- // --|RST XOUT|-
- // | |
- // | (TXD)P2.4|-----------> // ----> RXD(2)
- // | | 300~115200 bps
- // | (RXD)P2.5|<----------- // <---- TXD(3) PC(DB9)
- // | |
- // | GND |------------------------GND(5)
- //
- //******************************************************************************
- #include "msp430x42x.h"
- #define F_ACLK (32768) /*ACLK對應晶體頻率,勿修改*/
- char TxFlag=1;
- char RxFlag=0;
- /****************************************************************************
- * 名 稱:UART_Init()
- * 功 能:初始化串口。設置其工作模式及波特率。
- * 入口參數:
- * Baud 波特率 (300~115200)
- Parity 奇偶校驗位('n'=無校驗 'p'=偶校驗 'o'=奇校驗)
- DatsBits 數據位位數 (7或8)
- StopBits 停止位位數 (1或2)
- * 出口參數:返回值為1時表示初化成功,為0表示參數出錯
- * 范 例: UART_Init(9600,'n',8,1) //設成9600bps,無校驗,8位數據,1位停止位
- UART_Init(2400,'p',7,2) //設成2400bps,偶校驗,7位數據,2位停止位
- ****************************************************************************/
- char UART_Init(long int Baud,char Parity,char DataBits,char StopBits)
- {
- unsigned long int BRCLK; //波特率發生器時鐘頻率
- int FreqMul,FLLDx,BRDIV,BRMOD; //倍頻系數、DCO倍頻、波特率分頻系數、分頻尾數
- int i;
- unsigned char const ModTable[8]={0x00,0x08,0x88,0x2A,0x55,0x6B,0xdd,0xef};
- //分頻尾數所對應的調制系數(將0~7個"1"均勻分布在一個字節的8bit中)
- //-------------設置波特率發生器時鐘源,并計算波特率時鐘頻率--------------
- UTCTL0 &=~(SSEL0+SSEL1); //清除之前的時鐘設置
- if(Baud<=4800)
- {
- UTCTL0 |= SSEL0; //低于4800的波特率,用ACLK,降低功耗
- BRCLK=F_ACLK; //波特率發生器時鐘頻率=ACLK
- }
- else
- {
- UTCTL0 |= SSEL1; //高于4800的波特率,用SMCLK,保證速度
- FreqMul=(SCFQCTL&0x7F)+1; //獲得倍頻系數
- FLLDx=((SCFI0&0xC0)>>6)+1; //獲得DCO倍頻系數(DCOPLUS所帶來的額外倍頻)
- BRCLK=F_ACLK*FreqMul; //計算波特率發生器時鐘頻率=ACLK*倍頻系數
- if(FLL_CTL0&DCOPLUS) BRCLK*=FLLDx; //若開啟了DCOPLUS,還要計算額外倍頻
- }
- //------------------------設置波特率-------------------------
- if((Baud<300)||(Baud>115200)) return(0); //波特率范圍300-115200bps
- BRDIV=BRCLK/Baud; //計算波特率分頻系數(整數部分)
- BRMOD=((BRCLK*8)/Baud)%8; //計算波特率分頻尾數(除不盡的余數)
- UBR00 = BRDIV%256;
- UBR10 = BRDIV/256; //整數部分系數
- UMCTL0 = ModTable[BRMOD]; //余數部分系數
- //------------------------設置校驗位-------------------------
- switch(Parity)
- {
- case 'n':case'N': U0CTL&=~PENA; break; //無校驗
- case 'p':case'P': U0CTL|= PENA+PEV ;break; //偶校驗
- case 'o':case'O': U0CTL|= PENA; U0CTL&=~PEV;break;//奇校驗
- default : return(0); //參數錯誤
- }
- //------------------------設置數據位-------------------------
- switch(DataBits)
- {
- case 7:case'7': U0CTL&=~CHAR; break; //7位數據
- case 8:case'8': U0CTL|= CHAR; break; //8位數據
- default : return(0); //參數錯誤
- }
- //------------------------設置停止位-------------------------
- switch(StopBits)
- {
- case 1:case'1': U0CTL&=~SPB; break; //1位停止位
- case 2:case'2': U0CTL|= SPB; break; //2位停止位
- default : return(0); //參數錯誤
- }
- P2SEL |= 0x30; // P2.4,5 = USART0 TXD/RXD
- ME1 |= UTXE0 + URXE0; // Enable USART0 TXD/RXD
- UCTL0 &= ~SWRST; // Initialize USART state machine
- IE1 |= URXIE0+UTXIE0; // Enable USART0 RX interrupt
- _EINT();
- for(i=0;i<4000;i++); //略延遲,等待波特率分頻穩定
- return(1); //設置成功
- }
- /****************************************************************************
- * 名 稱:UART_LPM()
- * 功 能:串口收/發等待過程中,將CPU及時鐘系統關閉,休眠省電
- * 入口參數:無
- * 出口參數:無
- * 說 明: 若與其他外設的時鐘沖突,可注釋掉該函數,但會增加功耗。
- ****************************************************************************/
- void UART_LPM()
- {
- if(UTCTL0&SSEL0) LPM3; //若以ACLK 作時鐘,進入LPM3休眠(僅打開ACLK)
- else LPM0; //若以SMCLK作時鐘,進入LPM0休眠(不關閉SMCLK)
- }
- /****************************************************************************
- * 名 稱:UART_PutChar()
- * 功 能:從串口發送1字節數據
- * 入口參數:Chr: 待發送的一字節數據
- * 出口參數:無
- * 說 明: 在等待發送完畢的過程中,CPU會休眠
- ****************************************************************************/
- void UART_PutChar(char Chr)
- {
- while (TxFlag==0) UART_LPM(); // 等待上一字節發完,并休眠
- TxFlag=0; //小技巧:等上一字節發完,再發本字節,把字節間隔等待的時間讓給計算
- TXBUF0=Chr;
- }
- /****************************************************************************
- * 名 稱:UART_GetChar()
- * 功 能:從串口接收1字節數據
- * 入口參數:無
- * 出口參數:收到的一字節數據
- * 說 明: 如果串口沒有數據,會一直等待。等待過程中,CPU會休眠
- ****************************************************************************/
- char UART_GetChar(void)
- {
- while (RxFlag==0) UART_LPM(); // 收到一字節?
- RxFlag=0;
- return(RXBUF0);
- }
- /****************************************************************************
- * 名 稱:UART_IsRcvChar()
- * 功 能:判斷串口是否收到1字節數據
- * 入口參數:無
- * 出口參數:1表示有數據,0表示無數據
- * 說 明: 配合UART_GetChar()函數使用,先檢查到有數據再接收,可以消除阻塞
- ****************************************************************************/
- char UART_IsRcvChar()
- {
- return(RxFlag);
- }
- /****************************************************************************
- * 名 稱:UART_RX()
- * 功 能:串口接收中斷,每接收到1字節會發生一次中斷
- ****************************************************************************/
- #pragma vector=UART0RX_VECTOR
- __interrupt void UART_RX (void)
- {
- RxFlag=1;
- /*在這里添加用戶中斷服務程序代碼,如將數據壓入接收緩沖等*/
- __low_power_mode_off_on_exit();
- }
- /****************************************************************************
- * 名 稱:UART_TX()
- * 功 能:串口發送中斷,每發完1字節會發生一次中斷
- ****************************************************************************/
- #pragma vector=UART0TX_VECTOR
- __interrupt void UART_TX (void)
- {
- TxFlag=1;
- /*在這里添加用戶中斷服務程序代碼,如將數據從緩沖取出等*/
- __low_power_mode_off_on_exit();
- }
- /*===================以下是串口終端設備接口函數庫==========================*/
- #define LINE_LENGTH 20 /* 行緩沖區大小,決定每行最多輸入的字符數*/
- /*標準終端設備中,特殊ASCII碼定義,請勿修改*/
- #define In_BACKSP 0x08 /* ASCII <-- (退格鍵) */
- #define In_DELETE 0x7F /* ASCII <DEL> (DEL 鍵) */
- #define In_EOL '\r' /* ASCII <CR> (回車鍵) */
- #define In_SKIP '\3' /* ASCII control-C */
- #define In_EOF '\x1A' /* ASCII control-Z */
- #define Out_DELETE "\x8 \x8" /* VT100 backspace and clear */
- #define Out_SKIP "^C\n" /* ^C and new line */
- #define Out_EOF "^Z" /* ^Z and return EOF */
- #include "stdio.h"
- /****************************************************************************
- * 名 稱:putchar()
- * 功 能:向標準終端設備發送一字節數據(1個字符)
- * 入口參數:ch: 待發送的字符
- * 出口參數:發出的字符
- * 說 明: printf函數會調用該函數作為底層輸出。這里從串口輸出字符到PC機的超
- 級終端軟件上,printf的結果將打印到超級終端上。若修改該函數,將字
- 符以其他方式輸出,如顯示到LCD上,printf的結果將顯示在LCD上。
- ****************************************************************************/
- int putchar(int ch)
- {
- if (ch == '\n') // '\n'(回車)擴展成 '\n''\r' (回車+換行)
- {
- UART_PutChar(0x0d) ; //'\r'
- }
- UART_PutChar(ch); //從串口發出數據
- return (ch);
- }
- /****************************************************************************
- * 名 稱:put_message()
- * 功 能:向標準終端設備發送一個字符串
- * 入口參數:*s: 字符串(數組)頭指針(數組名)
- * 出口參數:無
- ****************************************************************************/
- static void put_message(char *s)
- {
- while (*s) //當前字符不為空 (字符串以0x00結尾)
- putchar(*s++); //輸出一個字符,指針指向下一字符
- }
- /****************************************************************************
- * 名 稱:getchar()
- * 功 能:從標準終端設備接收一字節數據(1個字符)
- * 入口參數:無
- * 出口參數:收到的字符
- * 說 明: scanf函數會調用該函數作為底層輸入。這里從PC機鍵盤借助超級終端軟
- 件通過串口輸入字符到單片機上。scanf函數的輸入即源自PC機鍵盤。若
- 修改該函數,將字符以其他方式輸入,如單片機IO口,可用按鈕向scanf
- 函數輸入數據。本函數帶有緩存,能夠處理退格等刪除操作。若不需要刪
- 除操作,可直接調用UART_GetChar()函數。
- ****************************************************************************/
- int getchar(void)
- {
- static char io_buffer[LINE_LENGTH + 2]; /* Where to put chars */
- static int ptr; /* Pointer in buffer */
- char c;
- for (;;)
- {
- if (io_buffer[ptr]) //如果緩沖區有字符
- return (io_buffer[ptr++]); //則逐個返回字符
- ptr = 0; //直到發送完畢為止,清空緩沖區指針
- while(1) //緩沖區沒有字符,才會執行到這里,開始等待字符輸入
- { c = UART_GetChar(); //等待串口接收一個字符
- if (c == In_EOF && !ptr) //----EOF鍵(Ctrl+Z)----
- { //EOF符只能在未輸入其他字符時才有效
- put_message(Out_EOF); //讓終端顯示EOF符
- return EOF; //返回EOF符
- }
- if ((c == In_DELETE)||(c==In_BACKSP)) //----退格或DEL鍵----
- {
- if (ptr)
- {
- ptr--; //從緩沖區刪掉一個字符
- put_message(Out_DELETE); //讓終端顯示也刪掉一個字符
- }
- }
- else if (c == In_SKIP) //-----取消鍵 Ctrl + C----
- {
- put_message(Out_SKIP); //讓終端顯示放棄本行跳到下一行
- ptr = LINE_LENGTH + 1; /* 這里永遠是0(結束符) */
- break;
- }
- else if (c == In_EOL) //--------遇到回車鍵------
- {
- putchar(io_buffer[ptr++] = '\n'); //讓終端顯示換行
- io_buffer[ptr] = 0; //末尾增添字符串結束字符NULL
- ptr = 0; //指針清空
- break; //跳出后開始返回數據
- }
- else if (ptr < LINE_LENGTH) //----正常ASCII碼字符----
- {
- if (c >= ' ') //刪除0x20以下的其他ASCII碼
- {
- putchar(io_buffer[ptr++] = c); //存入緩沖區
- }
- }
- else //--------沖區已滿--------
- {
- putchar('\7'); //向終端發送鳴響符,PC會響一聲,提示已滿
- }
- }
- }
- }
復制代碼
|
|