-
Obwohl bei PCs die seriellen Schnittstellen nach und nach verschwinden, können serielle Schnittstellen im Embedded-Bereich immer noch als beliebt bezeichnet werden, da sie kostengünstig und bequem zu programmieren sind. Auf Systemen ohne Bildschirme oder Eingabegeräte sind serielle Schnittstellen sogar noch beliebter . Unverzichtbar, zusammen mit HyperTerminal, löst es das Problem der Informationsanzeige und -eingabe.
Nach mehreren Tagen harter Arbeit steht die NativeSample-Transplantationsarbeit von .Net Micro Framework auf der Cortex-M3-Plattform kurz vor dem Erreichen eines Stadiums. Derzeit sind der Startup-Code, SRAM, Clock (RCC), Interrupt (NVIC), SysTick, fertig. GPIO, serieller Port, NandFlash (FMSC) und andere verwandte Funktionen. Diese Codes stellen den Mindestsatz dar, damit TinyClr normal funktioniert. Wenn diese als Grundlage dienen, kann der nächste Schritt darin bestehen, TinyClr zu transplantieren. Das von uns verwendete M3-Entwicklungsboard verfügt über mehr als 2 MB RAM, sodass unsere Arbeit zu diesem Zeitpunkt möglicherweise zu 90 % abgeschlossen ist. Aufgrund begrenzter Ressourcen muss der nächste Schritt des Debuggens jedoch die Flash-Version sein, sodass es viele unbekannte Arbeiten geben wird. und das Debuggen wird auch schwierig werden. Die Reise von .Net Micro Framework PortingKit wird jedoch ehrlich gesagt schwierig, aber lohnend sein auf ein neues Niveau verbessert.
Okay, lassen Sie uns über die Entwicklung des Treibers für die serielle Schnittstelle sprechen.
Wie bei der GPIO-Entwicklung müssen wir in CortexM3.h immer noch Registercode für die serielle Schnittstelle schreiben.
struct CortexM3_Usart
{
statische Konstante UINT32 c_MAX_BAUDRATE = 45000000;
statische Konstante UINT32 c_MIN_BAUDRATE = 1200;
static const UINT32 c_Base1 = 0x40013800;
statische Konstante UINT32 c_Base2 = 0x40004400;
statische Konstante 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;
};
Mit dem obigen Code können wir das Register der seriellen Schnittstelle problemlos bedienen.
Die Initialisierung der seriellen Schnittstelle erfordert die folgenden Initialisierungsarbeiten (das STM3210E-Entwicklungsboard verfügt über drei serielle Schnittstellen, wir nehmen als Beispiel die serielle Schnittstelle 1):
1. Schalten Sie die Uhr der seriellen Schnittstelle ein
UsartId = CortexM3_NVIC::c_IRQ_Index_USART1;
RCC.APB2ENR |= CortexM3_RCC::APB2_GPIOA |.
2. Aktivierungsunterbrechung
if(!CPU_INTC_ActivateInterruptEx( UsartId, (UINT32)(void *)USART1_IRQHandler)) return FALSE;
3. Stellen Sie die Parameter der seriellen Schnittstelle ein, z. B. Baudrate, Parität, Datenbits, Stoppbits usw.
leicht
4. GPIO-Neudefinition
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. Aktivierung der seriellen Schnittstelle
Usart.CR1 |= CortexM3_Usart::CR1_UE_Set;
Vervollständigen Sie das Senden und Empfangen von Daten in der Interrupt-Funktion:
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]))
{
zurückkehren;
}
if(USART_RemoveCharFromTxBuffer( comPort, c ))
{
WriteCharToTxBuffer( comPort, c );
}
anders
{
// weitere Tx-Interrupts deaktivieren, da wir Level-ausgelöst sind
TxBufferEmptyInterruptEnable(comPort, FALSE);
}
Events_Set( SYSTEM_EVENT_FLAG_COM_OUT );
}
}
Der Kerncode ist der oben eingeführte relevante Inhalt. Nachfolgend schreiben wir einen Testcode für die serielle Schnittstelle in 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("Hallo Micro Framework!!!rn");
}
}