?? uart0.c
字號:
/*********************************************************************
* Copyright (c) 2011-2012,李士偉
* All rights reserved.
*文 件 名:uart0.c
*描 述:串口0驅動代碼源文件
* 該串口實現多個任務先來先服務的策略
* 對于一個正在發送(接受)任務,它占有UART0SendingTCB(UART0ReceingTCB)
* 并設置發送(接收)字符閥值,每當發送(接收)完一個字符閥值遞減
* 直到中斷函數判斷閥值為0時喚醒正在等待發送(接收)完的任務
* 在發送(接收)期間阻塞其它的發送(接收)任務,
* 將被阻塞的任務按加入UART0SendWaitQ(UART0ReceWaitQ),
* 直到其發送(接收)完成,喚醒阻塞的任務
*當前版本:V1.02
*作 者:李士偉
*創建日期:2011.09.24
**********************************************************************/
/*********************************************************************
*版 本:V1.02
*修 改 人:李士偉
*修改日期:2012.01.07
*描 述:以中斷工作方式替換原來的查詢等待方式
**********************************************************************/
#include <kernel\asm.h>
#include <kernel\kds.h>
#include <kernel\kd.h>
#include <kernel\sched.h>
#include <kernel\chr_buf.h>
#include <kernel\flag.h>
#include <drivers\lpc2103\uart0.h>
#include <drivers\lpc2103\target.h>
#include <drivers\lpc2103\vic.h>
#include <drivers\lpc2103\pinsel.h>
static INT32U UART0SendValve; /* 發送完多少個字節喚醒發送任務 */
static INT32U UART0ReceValve; /* 接收完多少個字節喚醒接收任務 */
static OS_TCB *UART0SendingTCB; /* 正在等待發送完的任務 */
static OS_TCB *UART0ReceingTCB; /* 正在等待接收完的任務 */
static OS_TCB *UART0SendWaitQ; /* 等待發送隊列 */
static OS_TCB *UART0ReceWaitQ; /* 等待接收隊列 */
static OS_CHR_BCB *UART0SendBcb; /* 發送緩沖區控制塊 */
static OS_CHR_BCB *UART0ReceBcb; /* 接收緩沖區控制塊 */
/*********************************************************************
*函 數 名:UART0_SetBuf
*描 述:設置串口0的發送/接收緩沖區大小
*輸入參數:send_buf_size, 發送緩沖區大小
* rece_buf_size, 接收緩沖區大小
*輸出參數:無
*返 回 值:0,設置失敗,1,設置成功
*注 意:
**********************************************************************/
INT32U UART0_SetBuf(INT32U send_buf_size, INT32U rece_buf_size)
{
UART0SendBcb = OS_CreateChrBuf(send_buf_size);
if (UART0SendBcb == NULL)
{
return 0;
}
UART0ReceBcb = OS_CreateChrBuf(rece_buf_size);
if (UART0ReceBcb == NULL)
{
OS_FreeChrBuf(UART0SendBcb);
return 0;
}
return 1;
}
/*********************************************************************
*函 數 名:UART0_Init
*描 述:初始化串口0
*輸入參數:
* baud:波特率
* bits: 字長度,可選5,6,7,8
* stopbits: 停止位位數,取值1或2
* stopbits == 2 時 如果字長5位,則停止位1.5位
* parity: 校驗選擇
* parity == 0 奇檢驗
* parity == 1 偶校驗
* parity == 2 校驗位強制為"1"
* parity == 3 校驗位強制為"0"
* parity == 4 不校驗
*輸出參數:無
*返 回 值:無
*注 意:為防止在未設置緩沖區的情況下接收到字符
* 最好是先調用UART0_SetBuf設置完緩沖區在調用該函數初始化UART0
**********************************************************************/
INT32U UART0_Init(INT32U baud, INT32U bits, INT32U stopbits, INT32U parity)
{
INT8U Reg = 0;
INT16U Fdiv;
/* 參數檢查 */
if ((bits < 5) || (bits > 8)
|| (stopbits < 1) || (stopbits > 2)
|| (parity > 4))
{
return 0;
}
if (PIN_Configure(PIN_TXD0))
{
if (PIN_Configure(PIN_RXD0) == 0)
{
PIN_Release(PIN_TXD0);
return 0;
}
}
Reg = bits-5; /* 設置字長度 */
Reg |= ((stopbits - 1) << 2); /* 設置停止位數 */
if (parity < 4)
{
Reg |= (parity << 4) + 8; /* 設置校驗 */
}
Reg |= 0x80; /* DLAB = 1 */
U0LCR = 0;
U0LCR = Reg; /* U0LCR */
/* 設置波特率 */
Fdiv = (Fpclk / 16) / baud;
U0DLM = Fdiv >> 8;
U0DLL = Fdiv & 0xff;
U0LCR &= 0x7f;
U0IER = 3; /* 開發送和接收中斷 */
U0TER = 0x80; /* 發送使能 */
UART0SendValve = 0;
UART0ReceValve = 0;
UART0SendWaitQ = NULL;
UART0ReceWaitQ = NULL;
UART0SendingTCB = NULL;
UART0ReceingTCB = NULL;
/* 注冊UART0中斷例程 */
VIC_RegisterIRQ(UART0_Handler, UART0_INTR_NUM, UART0_INTR_PRIO);
return 1;
}
/*********************************************************************
*函 數 名:UART0_ISR
*描 述:UART0中斷服務例程
*輸入參數:無
*輸出參數:無
*返 回 值:無
*注 意:該例程根據讀取U0IIR(讀取時自動消除中斷標志)
* 判斷UART0產生什么中斷,執行相應的操作
**********************************************************************/
void UART0_ISR(void)
{
INT8U ch, IIR;
IIR = U0IIR;
if (IIR & 0x2) /* THRE 中斷 */
{
if (UART0SendingTCB == NULL) /* 防止沒有任務在等待發送完 */
{
goto __end_uart0_send_isr;
}
UART0SendValve--;
if (OS_GetChrBufByte(UART0SendBcb, &ch)) /* 緩沖區還有未發送的數據 */
{
U0THR = ch;
}
if (UART0SendValve == 0) /* 閥值為0,喚醒等待發送完的任務 */
{
OS_EnterRunQ(UART0SendingTCB);
}
}
__end_uart0_send_isr:
if (IIR & 0x4) /* 接收到字符 */
{
ch = U0RBR;
if (UART0ReceingTCB == NULL) /* 防止沒有任務在等待接收完 */
{
goto __end_uart0_rece_isr;
}
UART0ReceValve--;
OS_PutChrBufByte(UART0ReceBcb, ch); /* 將接收的字符輸入到接收緩沖區 */
if (UART0ReceValve == 0) /* 閥值為0,喚醒等待接收完的任務 */
{
OS_EnterRunQ(UART0ReceingTCB);
}
}
__end_uart0_rece_isr:
VICVectAddr = 0x00; /* 通知VIC中斷處理完 */
}
/*********************************************************************
*函 數 名:UART0_SendByte
*描 述:發送一個字節
*輸入參數:b:字節
*輸出參數:無
*返 回 值:無
*注 意:該函數在將數據送入到U0THR,阻塞任務并調度,
* 直到發送完,才喚醒任務,
* 任務被喚醒時喚醒一個其它等待發送的任務
**********************************************************************/
void UART0_SendByte(INT8U b)
{
OS_ENTER_CRITICAL();
for ( ; ; )
{
if (UART0SendingTCB != NULL) /* 判斷是否有任務正在發送數據 */
{
/* 有任務在發送數據,進入等待發送隊列 */
OS_EnterWaitQTail(&UART0SendWaitQ, OSTCBCur);
OS_Sched();
continue ;
}
break ;
}
UART0SendValve = 1; /* 設置閥值1,發送完一個字節就喚醒任務 */
OS_EnterWaitQTail(&UART0SendingTCB, OSTCBCur); /* 進入到等待發送完隊列 */
U0THR = b; /* 發送數據 */
OS_EXIT_CRITICAL();
OS_Sched();
if (UART0SendWaitQ != NULL)
{
OS_EnterRunQ(UART0SendWaitQ); /* 喚醒其它任務發送數據 */
}
OS_Sched();
return ;
}
/*********************************************************************
*函 數 名:UART0_SendNBytes
*描 述:發送N個字節
*輸入參數:pbyte_arr: 字節數組指針
* n:發送字節數
*輸出參數:無
*返 回 值:無
*注 意:該函數區別于UART0_SendByte的地方是它將數據送入緩沖區,
* 并從緩沖區獲取第一個字節送入發送寄存器
**********************************************************************/
void UART0_SendNBytes(INT8U *pbyte_arr, INT32U n)
{
INT8U tx;
/* 錯誤參數檢查 */
if (pbyte_arr == NULL || n == 0)
{
return ;
}
OS_ENTER_CRITICAL();
for ( ; ; )
{
if (UART0SendingTCB != NULL) /* 判斷是否有任務正在發送數據 */
{
/* 有任務在發送數據,進入等待發送隊列 */
OS_EnterWaitQTail(&UART0SendWaitQ, OSTCBCur);
OS_Sched();
continue ;
}
break ;
}
UART0SendValve = n; /* 設置閥值,發送完n個字節喚醒任務 */
OS_EnterWaitQTail(&UART0SendingTCB, OSTCBCur);
OS_PutChrBufNBytes(UART0SendBcb, pbyte_arr, n); /* 將數據送入發送緩沖區 */
OS_GetChrBufByte(UART0SendBcb, &tx); /* 從緩沖區獲取一個字節發送 */
U0THR = tx; /* 發送,發送完觸發中斷 */
OS_EXIT_CRITICAL();
OS_Sched();
if (UART0SendWaitQ != NULL)
{
OS_EnterRunQ(UART0SendWaitQ); /* 喚醒其它任務發送數據 */
}
OS_Sched();
return ;
}
/*********************************************************************
*函 數 名:UART0_ReceByte
*描 述:接收一個字節
*輸入參數:無
*輸出參數:無
*返 回 值:返回字節
*注 意:
**********************************************************************/
INT8U UART0_ReceByte(void)
{
INT8U ch;
OS_ENTER_CRITICAL();
for ( ; ; )
{
if (UART0ReceingTCB != NULL)
{
OS_EnterWaitQTail(&UART0ReceWaitQ, OSTCBCur);
OS_Sched();
continue ;
}
break ;
}
UART0ReceValve = 1;
OS_EnterWaitQTail(&UART0ReceingTCB,OSTCBCur);
OS_Sched();
OS_GetChrBufByte(UART0ReceBcb, &ch);
OS_EXIT_CRITICAL();
if (UART0ReceWaitQ != NULL)
{
OS_EnterRunQ(UART0ReceWaitQ); /* 喚醒其它任務發送數據 */
}
OS_Sched();
return ch;
}
/*********************************************************************
*函 數 名:UART0_ReceNBytes
*描 述:接收N個字節
*輸入參數:n:接收字節數
*輸出參數:pbyte_arr: 字節串接收容器
*返 回 值:無
*注 意:
**********************************************************************/
void UART0_ReceNBytes(INT8U *pbyte_arr, INT32U n)
{
if (pbyte_arr == NULL || n == 0)
{
return ;
}
OS_ENTER_CRITICAL();
for ( ; ; )
{
if (UART0ReceingTCB != NULL)
{
OS_EnterWaitQTail(&UART0ReceWaitQ, OSTCBCur);
OS_Sched();
continue ;
}
break;
}
UART0ReceValve = n;
OS_EnterWaitQTail(&UART0ReceingTCB,OSTCBCur);
OS_Sched();
OS_GetChrBufNBytes(UART0ReceBcb, pbyte_arr, n);
OS_EXIT_CRITICAL();
if (UART0ReceWaitQ != NULL)
{
OS_EnterRunQ(UART0ReceWaitQ); /* 喚醒其它任務發送數據 */
}
OS_Sched();
}
/*********************************************************************
*函 數 名:UART0_putc
*描 述:發送一個字符
*輸入參數:ch:字符
*輸出參數:無
*返 回 值:無
*注 意:
**********************************************************************/
void UART0_putc(char ch)
{
UART0_SendByte((INT8U) ch);
}
/*********************************************************************
*函 數 名:UART0_puts
*描 述:發送一個字符串
*輸入參數:str:字符串指針
*輸出參數:無
*返 回 值:無
*注 意:
**********************************************************************/
void UART0_puts(char *str)
{
INT32U i = 0;
while (*(str + i++) != '\0')
;
if (i == 1)
{
return ;
}
UART0_SendNBytes((INT8U*)str, --i);
}
/*********************************************************************
*函 數 名:UART0_getc
*描 述:接收一個字符
*輸入參數:無
*輸出參數:無
*返 回 值:接收到的字符
*注 意:
**********************************************************************/
char UART0_getc(void)
{
return (char)UART0_ReceByte();
}
/*********************************************************************
*函 數 名:UART0_gets
*描 述:接收一個字符串
*輸入參數:無
*輸出參數:s: 接收字符串容器指針
*返 回 值:無
*注 意:回車,換行自動轉化字符串結束標志
**********************************************************************/
void UART0_gets(char *s)
{
for ( ; ; )
{
*s=(char)UART0_ReceByte();
/* 回車,換行自動轉化字符串結束標志 */
if (*s == 13 || *s == 10)
{
*s = '\0';
return ;
}
s++;
}
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -