-
雖然在PC機中,串口漸行漸遠,但是在嵌入式領域,串口仍可以說是如日中天,因為它造價低廉、並且編程也比較方便,在沒有顯示屏或輸入設備的系統上,串口更是不可或缺,和超級終端一道,共同解決了資訊顯示和輸入問題。
經過這幾天的努力,在Cortex-M3平台上的.Net Micro Framework的NativeSample移植工作就要一個段落了,目前已實現啟動代碼、SRAM、時鐘(RCC)、中斷(NVIC)、SysTick、GPIO、串口、NandFlash(FMSC)等相關功能,這些程式碼可以說是讓TinyClr正常運作的最小集合,有了這些工作做鋪墊,下一步就可以移植TinyClr了,如果我們採用的Cortex-M3開發板有2M以上的RAM,那麼我們的工作到這一步也許是已經完成90%上了,但是由於資源有限,下一步調試必須為Flash版本,所以未知的工作將很多,並且調試也將變得困難,不管怎麼我們的.Net Micro Framework PortingKit之旅還將繼續,不過,說心裡話,由零開始完成這些工作,雖然艱苦,但是收穫頗豐,對ARM開發(尤其是Cortex-M3)的理解更是上了一個層次。
好了,下面我們要說一下串口驅動的開發。
和GPIO開發一樣,我們仍需在CortexM3.h中編寫串口相關的暫存器程式碼。
struct CortexM3_Usart
{
static const UINT32 c_MAX_BAUDRATE = 45000000;
static const UINT32 c_MIN_BAUDRATE = 1200;
static const UINT32 c_Base1 = 0x40013800;
static const UINT32 c_Base2 = 0x40004400;
static const UINT32 c_Base3 = 0x40004800;
/****/ volatile UINT16 SR;
static const UINT16 SR_TXE=((UINT16)0x0080);
static const UINT16 SR_TC=((UINT16)0x0040);
static const UINT16 SR_RXNE=((UINT16)0x0020);
UINT16 RESERVED0;
/****/ volatile UINT16 DR;
UINT16 RESERVED1;
/****/ volatile UINT16 BRR;
UINT16 RESERVED2;
/****/ volatile UINT16 CR1;
static const UINT16 CR1_UE_Set = ((UINT16)0x2000); //USART Enable Mask
static const UINT16 CR1_UE_Reset = ((UINT16)0xDFFF); //USART Disable Mask
static const UINT16 CR1_Parity_No = ((UINT16)0x0000);
static const UINT16 CR1_Parity_Even = ((UINT16)0x0400);
static const UINT16 CR1_Parity_Odd = ((UINT16)0x0600);
static const UINT16 CR1_DataBit_8 = ((UINT16)0x0000);
static const UINT16 CR1_DataBit_9 = ((UINT16)0x1000);
static const UINT16 CR1_Mode_Rx = ((UINT16)0x0004);
static const UINT16 CR1_Mode_Tx = ((UINT16)0x0008);
static const UINT16 CR1_CLEAR_Mask = ((UINT16)0xE9F3);
static const UINT16 CR1_PEIE = ((UINT16)0x0100);
static const UINT16 CR1_TXEIE = ((UINT16)0x0080);
static const UINT16 CR1_TCIE = ((UINT16)0x0040);
static const UINT16 CR1_RXNEIE = ((UINT16)0x0020);
UINT16 RESERVED3;
/****/ volatile UINT16 CR2;
static const UINT16 CR2_StopBits_1 = ((UINT16)0x0000);
static const UINT16 CR2_StopBits_0_5 = ((UINT16)0x1000);
static const UINT16 CR2_StopBits_2 = ((UINT16)0x2000);
static const UINT16 CR2_StopBits_1_5 = ((UINT16)0x3000);
static const UINT16 CR2_StopBits_Mask= ((UINT16)0xCFFF); /* USART CR2 STOP Bits Mask */
UINT16 RESERVED4;
/****/ volatile UINT16 CR3;
static const UINT16 CR3_HardwareFlowControl_None = ((UINT16)0x0000);
static const UINT16 CR3_HardwareFlowControl_RTS = ((UINT16)0x0100);
static const UINT16 CR3_HardwareFlowControl_CTS = ((UINT16)0x0200);
static const UINT16 CR3_HardwareFlowControl_RTS_CTS = ((UINT16)0x0300);
static const UINT16 CR3_HardwareFlowControl_Mask = ((UINT16)0xFCFF);
UINT16 RESERVED5;
/****/ volatile UINT16 GTPR;
UINT16 RESERVED6;
};
有了上述程式碼,我們便可以方便的操作串口暫存器了。
串列埠的初始化要做如下初始化工作(STM3210E開發板有三個串列埠,我們以串列埠1為例來敘述):
1、 開啟串口時鐘
UsartId = CortexM3_NVIC::c_IRQ_Index_USART1;
RCC.APB2ENR |= CortexM3_RCC::APB2_GPIOA | CortexM3_RCC::APB2_USART1;
2、 啟動中斷
if(!CPU_INTC_ActivateInterruptEx( UsartId, (UINT32)(void *)USART1_IRQHandler)) return FALSE;
3、 設定串列埠參數,如波特率、奇偶校驗、資料位元、停止位元等
略
4、 GPIO重定義
CPU_GPIO_DisablePin(GPIO_Driver::PA9,RESISTOR_DISABLED,FALSE,GPIO_ALT_MODE_1);
CPU_GPIO_DisablePin(GPIO_Driver::PA10,RESISTOR_DISABLED,TRUE,GPIO_ALT_MODE_2);
5、 串口使能
Usart.CR1 |= CortexM3_Usart::CR1_UE_Set;
在中斷函數中完成資料的發送和接收:
void CortexM3_USART_Driver::ISR( void* param )
{
UINT32 comPort = (UINT32)param;
CortexM3_Usart &Usart=CortexM3::Usart(comPort);
char c;
UINT32 Status;
Status = Usart.SR;
if(Status & CortexM3_Usart::SR_RXNE)
{
c = Usart.DR;
USART_AddCharToRxBuffer( comPort, c );
Events_Set( SYSTEM_EVENT_FLAG_COM_IN );
}
if(Status & CortexM3_Usart::SR_TC)
{
if(0 == (c_RefFlagTx & g_CortexM3_USART_Driver.m_RefFlags[comPort]))
{
return;
}
if(USART_RemoveCharFromTxBuffer( comPort, c ))
{
WriteCharToTxBuffer( comPort, c );
}
else
{
// disable further Tx interrupts since we are level triggered
TxBufferEmptyInterruptEnable( comPort, FALSE );
}
Events_Set( SYSTEM_EVENT_FLAG_COM_OUT );
}
}
核心程式碼也就是上述介紹的相關內容,以下我們在NativeSample中寫一個串列埠測試程式碼:
void ApplicationEntryPoint()
{
while(TRUE)
{
if(Events_WaitForEvents(SYSTEM_EVENT_FLAG_COM_IN,100))
{
Events_Clear(SYSTEM_EVENT_FLAG_COM_IN);
char bytData[512];
int Size=USART_BytesInBuffer(0,TRUE);
USART_Read(0,bytData,Size);
for(int i=0;i<Size;i++)
debug_printf("%c",bytData[i]);
}
debug_printf("Hello Micro Framework!!!rn");
}
}