Mikrokontrolery ARM (LPC2134)
obsługa interfejsu UART
w pooling'u
Białystok, styczeń 2015
Andrzej Pawluczuk: Mikrokontrolery ARM (LPC2134) obsługa interfejsu UART w pooling'u -2/24-
Copyright (C) 2015, Andrzej Pawluczuk. email: apawluczuk@vp.pl
Wszystkie prawa zastrzeżone.
Redystrybucja i używanie, czy to w formie tekstu zródłowego, czy w formie kodu
wykonywalnego, są dozwolone pod warunkiem spełnienia poniższych warunków:
1. Redystrybucja tekstu zródłowego musi zawierać powyższe zastrzeżenie własności
praw autorskich, niniejszą listę warunków oraz poniższe oświadczenie o
wyłączeniu odpowiedzialności.
2. Redystrybucja kodu wykonywalnego musi zawierać w dokumentacji lub w innych
materiałach dostarczanych wraz z kopią oprogramowania powyższe zastrzeżenie
własności praw autorskich, niniejszą listę warunków oraz poniższe oświadczenie
o wyłączeniu odpowiedzialności.
3. Nazwisko autora nie może być użyte celem sygnowania lub promowania
produktów pochodzących od tego opracowania, bez szczególnego, wyrażonego
na piśmie zezwolenia.
To opracowanie jest dostarczone przez posiadacza praw autorskich takim, jakie jest .
Każda, dorozumiana lub bezpośrednio wyrażona gwarancja, nie wyłączając dorozumianej
gwarancji przydatności handlowej i przydatności do określonego zastosowania, jest
wyłączona. W żadnym wypadku posiadacz praw autorskich nie może być odpowiedzialny
za jakiekolwiek bezpośrednie, pośrednie, incydentalne, specjalne, uboczne i wtórne szkody
(nie wyłączając obowiązku dostarczenia produktu zastępczego lub serwisu,
odpowiedzialności z tytułu utraty walorów użytkowych, utraty danych lub korzyści, a także
przerw w pracy przedsiębiorstwa) spowodowane w jakikolwiek sposób i na podstawie
istniejącej w torii odpowiedzialności kontraktowej, całkowitej lub deliktowej (wynikłej
zarówno z niedbalstwa, jak i innych postaci winy), powstałe w jakikolwiek sposób w
wyniku używania lub mające związek z używaniem oprogramowania, nawet jeśli o
możliwości powstania takich szkód ostrzeżono.
Andrzej Pawluczuk: Mikrokontrolery ARM (LPC2134) obsługa interfejsu UART w pooling'u -3/24-
ednym wręcz z naturalnych sposobów komunikowania się z systemem
zbudowanym na bazie mikrokontrolerów jest zastosowanie asynchronicznej
J
transmisji szeregowej (UART). W poniższym przykładzie programu
wykorzystany jest UART1. Użycie popularnych sterowników RS232 interfejsu
UART pozwala na proste przyłączenie urządzenia z mikrokontrolerem do komputera
PC (choć w najnowszych modelach niestety wyginęło odpowiednie złącze).
Do komunikacji z mikrokontrolerem od strony komputera PC użyty jest
standardowy program HyperTerminal (który również w najnowszych wersjach
windozy wyginął). W programie tym należy określić parametry transmisji
szeregowej następująco:
prędkość transmisji 9600,
8 bitów danych,
bez bitu parzystości,
z 1 bitem stopu.
Powyższe parametry odpowiadają parametrom transmisji szeregowej
zastosowanej z systemie. W mikrokontrolerach ARM z rodziny LPC2000 do
sterowania transmisją szeregową używany jest sygnał zegarowy, którym jest
taktowany rdzeń mikrokontrolera. Częstotliwość tego sygnału zegarowego jest
podzielona w odpowiednim dzielniku dając oczekiwaną prędkość transmisji. Należy
pamiętać, że na częstotliwość taktującą mają wpływ następujące elementy:
częstotliwość zewnętrznego rezonatora kwarcowego przyłączonego do
mikrokontrolera,
współczynniki (podzielnika i pomnożnika [P i M]) sterujące układem PLL,
podzielnik z zespole VPB.
Rys. 1: Elementy wpływające na częstotliwość taktującą w mikrokontrolerach LPC2000
W użytym rozwiązaniu sprzętowym zastosowany jest rezonator kwarcowy o
częstotliwości 12MHz. Wszystkie pozostałe parametry mające wpływ na
częstotliwość wygenerowanego sygnału taktującego podzespoły peryferyjne (między
innymi UART1) są określone w oprogramowaniu (patrz: plik system.h). Są to:
Andrzej Pawluczuk: Mikrokontrolery ARM (LPC2134) obsługa interfejsu UART w pooling'u -4/24-
(...)
// PLL setup const
#define FOSC ( 12000000 ) // Master Oscillator Freq.
#define PLL_MUL ( 5 ) // PLL Multiplier
#define PLL_DIV ( 2 ) // PLL Divider
#define CCLK (FOSC * PLL_MUL) // CPU Clock Freq.
(...)
// Pheripheral Bus Speed Divider
#define PBSD 2
#define PCLK ( CCLK / PBSD ) // Pheripheal Bus Clock Freq.
(...)
Parametry te są użyte do zaprogramowania odpowiednich podzespołów
(patrz funkcja: SysInit w pliku system.c).
Jak łatwo zauważyć, przy uwzględnieniu wartości parametrów, częstotliwość
sygnału taktującego UART wynosi 30MHz (patrz: PCLK w powyższych
ustawieniach: (12MHz * 5 ) / 2 = 30MHz). Inicjując UART do pracy i chcąc
uzyskać prędkość transmisji 9600, należy zaprogramować dzielnik w samym zespole
UART na odpowiednią wartość uwzględniając, że sam UART wewnętrznie dzieli
częstotliwość przez 16.
Przykładowy program prezentujący obsługę UART w trybie pooling jest
następujący:
Komentarz jest zawarty jedynie w miejscach istotnych z punktu widzenia
obsługi UART.
(...)
#include "LPC213x.H"
#include "system.h"
#include "lcdlib.h"
#include "irqservice.h"
#include "serialconst.h"
#include "uart1pol.h"
#define LED1Pin 27
#define LED2Pin 28
#define LED3Pin 29
volatile ULONG GeneralTimerConter ;
volatile ULONG LifeLEDDelayCounter ;
static UCHAR LEDState ;
static const UCHAR HelloText1 [ ] = "**** Hello! ****" ;
static const UCHAR HelloText2 [ ] = "Obsl. UART1.pool" ;
static const UCHAR UARTHelloText [ ] = "Witaj koles przy terminalu." ;
static void T0_IRQHandler ( void ) __irq ;
static void T0_IRQHandler ( void )
{
GeneralTimerConter ++ ;
LifeLEDDelayCounter ++ ;
Andrzej Pawluczuk: Mikrokontrolery ARM (LPC2134) obsługa interfejsu UART w pooling'u -5/24-
if ( LifeLEDDelayCounter >= 1000 )
{
LifeLEDDelayCounter = 0 ;
IOSET0 = ( ( ULONG ) 1 << LED1Pin ) |
( ( ULONG ) 1 << LED2Pin ) |
( ( ULONG ) 1 << LED3Pin ) ;
switch ( LEDState )
{
case 0 :
IOCLR0 = ( ULONG ) 1 << LED1Pin ;
break ;
case 1 :
break ;
case 2 :
IOCLR0 = ( ULONG ) 1 << LED2Pin ;
break ;
case 3 :
break ;
case 4 :
IOCLR0 = ( ULONG ) 1 << LED3Pin ;
break ;
case 5 :
break ;
} /* switch */ ;
LEDState ++ ;
if ( LEDState > 5 )
LEDState = 0 ;
} /* if */ ;
T0IR = 1 ;
VICVectAddr = 0 ;
} /* T0_IRQHandler */
static void HardwareInit ( void )
{
T0MR0 = 14999 ;
T0MCR = 3 ;
T0TCR = 1 ;
InstallIrqSerivce ( TIMER0_INT , ( void * ) T0_IRQHandler ) ;
} /* HardwareInit */
static void InitLEDDisplayEnvir ( void )
{
IODIR0 |= ( ( ULONG ) 1 << LED1Pin ) |
( ( ULONG ) 1 << LED2Pin ) |
( ( ULONG ) 1 << LED3Pin ) ;
IOSET0 = ( ( ULONG ) 1 << LED1Pin ) |
( ( ULONG ) 1 << LED2Pin ) |
( ( ULONG ) 1 << LED3Pin ) ;
} /* InitLEDDisplayEnvir */
static void EnvirInit ( void )
{
InitLCDEnvir ( ) ;
UART1InitEnvir ( ) ;
Zainicjowanie środowiska dla UART1 (zdefiniowanie funkcji pinów
portu, że są wyjściami UART1 a nie są wyprowadzeniami do ogólnego
zastosowania).
Andrzej Pawluczuk: Mikrokontrolery ARM (LPC2134) obsługa interfejsu UART w pooling'u -6/24-
InitLEDDisplayEnvir ( ) ;
} /* EnvirInit */
static void SoftInit ( void )
{
GeneralTimerConter = 0 ;
LifeLEDDelayCounter = 0 ;
LEDState = 0 ;
} /* SoftInit */
static void Wait ( ULONG Ticks )
{
ULONG StartTimer ;
ULONG TimeDiff ;
/*-------------------------------------------*/
StartTimer = GeneralTimerConter ;
for ( ; ; )
{
TimeDiff = GeneralTimerConter - StartTimer ;
if ( TimeDiff > Ticks )
break ;
} /* for */ ;
} /* Wait */
static const UCHAR ServicePromptText [ ] = "Nacinales: " ;
static const UCHAR ServiceControlCharText [ ] = "znak kontrolny" ;
static const UCHAR ServiceOutRangeText [ ] = "znak niestandardowy" ;
static void Service ( UCHAR Ch )
{
/*-------------------------------------------*/
UART1SendFlashString ( ServicePromptText ) ;
if ( Ch < 0x20 )
{
UART1SendFlashString ( ServiceControlCharText ) ;
} /* if ... */
else
{
if ( Ch >= 0x80 )
{
UART1SendFlashString ( ServiceOutRangeText ) ;
} /* if ... */
else
{
UART1Send ( Ch ) ;
} /* if ... else */ ;
} /* if ... else */ ;
UART1SendNewLine ( ) ;
} /* Service */
int main ( void )
{
SysInit ( ) ;
HardwareInit ( ) ;
EnvirInit ( ) ;
Andrzej Pawluczuk: Mikrokontrolery ARM (LPC2134) obsługa interfejsu UART w pooling'u -7/24-
Zainicjowanie środowiska (zawiera w sobie zainicjowanie UART1).
SoftInit ( ) ;
UART1Init( PCLK , N81Mode , 9600 ) ;
Skonfigurowanie UART1 do pracy w określonym trybie pracy oraz z
odpowiednią prędkością transmisji.
EnableIRQ ( ) ;
Wait ( 20 ) ;
InitialiseLCD ( ) ;
ClrScrLCD ( ) ;
WriteFlashTextLCD ( HelloText1 ) ;
NewLineLCD ( ) ;
WriteFlashTextLCD ( HelloText2 ) ;
UART1SendFlashString ( UARTHelloText ) ;
UART1SendNewLine ( ) ;
for ( ; ; )
{
UART1Pool ( ) ;
Wywołanie poolingowej obsługi UART, która może zmodyfikować dane
zawarte w buforze cyklicznym.
if ( UART1DataPresent ( ) )
{
Sprawdzenie, czy w buforze cyklicznym znajdują się dane do odczytu,
które w pewnym przypadku
Service ( UART1GetData ( ) ) ;
są odczytane i przekazane do interpretacji (patrz wyżej funkcja: Service).
} /* if */ ;
} /* loop */ ;
} /* main */
Powyższy program korzysta z następujących modułów:
Moduł IRQService (irqservice.h oraz irqservice.c)
(...)
#ifndef _irqservice_
#define _irqservice_
#include "types.h"
#define __irq __attribute__((interrupt("IRQ")))
#define I_Bit 0x80
#define F_Bit 0x40
#define SYS32Mode 0x1F
#define IRQ32Mode 0x12
Andrzej Pawluczuk: Mikrokontrolery ARM (LPC2134) obsługa interfejsu UART w pooling'u -8/24-
#define FIQ32Mode 0x11
#define WDT_INT 0
#define SWI_INT 1
#define ARM_CORE0_INT 2
#define ARM_CORE1_INT 3
#define TIMER0_INT 4
#define TIMER1_INT 5
#define UART0_INT 6
#define UART1_INT 7
#define PWM0_INT 8
#define I2C0_INT 9
#define SPI0_INT 10
#define SPI1_INT 11
#define PLL_INT 12
#define RTC_INT 13
#define EINT0_INT 14
#define EINT1_INT 15
#define EINT2_INT 16
#define EINT3_INT 17
#define ADC0_INT 18
#define I2C1_INT 19
#define BOD_INT 20
#define ADC1_INT 21
#define IRQ_SLOT_EN 0x20 /* bit 5 in Vector control register */
#define VIC_SIZE 16
#define VECT_ADDR_INDEX 0x100
#define VECT_CNTL_INDEX 0x200
extern void InitIrqSystem ( void ) ;
extern ULONG InstallIrqSerivce ( ULONG /* IrqNumber */ ,
void * /* IrqHandlerAddr */ ) ;
#endif
(...)
#include "lpc213x.h"
#include "types.h"
#include "irqservice.h"
static void DefaultIrqHandler ( void ) __irq ;
static void DefaultIrqHandler ( void )
{
VICVectAddr = 0 ;
while ( 1 )
{
} /* while */ ;
} /* DefaultIrqHandler */
void InitIrqSystem ( void )
{
USHORT Loop ;
ULONG * VectAddr ;
Andrzej Pawluczuk: Mikrokontrolery ARM (LPC2134) obsługa interfejsu UART w pooling'u -9/24-
ULONG * VectControl ;
/*-------------------------------------------*/
VICIntEnClr = 0xffffffff ;
VICVectAddr = 0 ;
VICIntSelect = 0 ;
for ( Loop = 0 ; Loop < VIC_SIZE ; Loop ++ )
{
VectAddr = (ULONG*) (VIC_BASE_ADDR+VECT_ADDR_INDEX+(Loop<<2)) ;
VectControl = (ULONG*) (VIC_BASE_ADDR+VECT_CNTL_INDEX+(Loop<<2)) ;
* VectAddr = 0 ;
* VectControl = 0 ;
} /* for */ ;
VICDefVectAddr = ( ULONG ) DefaultIrqHandler ;
} /* InitIrqSystem */
ULONG InstallIrqSerivce ( ULONG IrqNumber,
void * IrqHandlerAddr )
{
USHORT Loop ;
ULONG * VectAddr ;
ULONG * VectControl ;
/*-------------------------------------------*/
VICIntEnClr = 1 << IrqNumber ;
for ( Loop = 0 ; Loop < VIC_SIZE ; Loop ++ )
{
VectAddr = (ULONG*) (VIC_BASE_ADDR+VECT_ADDR_INDEX+(Loop<<2)) ;
if ( ( * VectAddr ) == ( ULONG ) 0 )
{
* VectAddr = ( ULONG ) IrqHandlerAddr ;
VectControl = (ULONG*) (VIC_BASE_ADDR+VECT_CNTL_INDEX+(Loop<<2)) ;
* VectControl = ( ULONG ) ( IRQ_SLOT_EN | IrqNumber ) ;
VICIntEnable = 1 << IrqNumber ;
return ( TRUE ) ;
} /* if */ ;
} /* for */ ;
return ( FALSE ) ;
} /* InstallIrqSerivce */
Moduł LCDLib (lcdlib.h oraz lcdlib.c)
(...)
#ifndef _lcdlib_
#define _lcdlib_
#include "types.h"
extern void InitLCDEnvir ( void ) ;
extern void InitialiseLCD ( void ) ;
extern void SetCursorPos ( UCHAR /* ColumnNo */ ,
UCHAR /* LineNo */ ) ;
extern void ClrScrLCD ( void ) ;
extern void HomeLCD ( void ) ;
extern void NewLineLCD ( void ) ;
Andrzej Pawluczuk: Mikrokontrolery ARM (LPC2134) obsługa interfejsu UART w pooling'u -10/24-
extern void SetCursonOn ( UCHAR /* BlinkMode */ ) ;
extern void SetCursonOff ( void ) ;
extern void WriteChLCD ( UCHAR /* Data */ ) ;
extern void WriteTextLCD ( UCHAR * /* Text */ ) ;
extern void WriteFlashTextLCD ( const UCHAR * /* Text */ ) ;
extern void ClearLine ( UCHAR /* RowNo */ ) ;
#endif
(...)
#include "lcdlib.h"
#include "lpc213x.h"
/*****************************************************
* Specyfikacja sprzetowa *
*****************************************************/
/* PINS:
- DB4 = P0.17
- DB5 = P0.18
- DB6 = P0.19
- DB7 = P0.20
- E = P0.21
- RW = P0.23
- RS = P0.22
*/
#define lcd_BackLight_pin 7
#define lcd_E_pin 21
#define lcd_RW_pin 23
#define lcd_RS_pin 22
#define lcd_DB4_pin 17
#define lcd_DB5_pin 18
#define lcd_DB6_pin 19
#define lcd_DB7_pin 20
#define PIN_E ( ( ULONG ) 1 << lcd_E_pin )
#define PIN_RW ( ( ULONG ) 1 << lcd_RW_pin )
#define PIN_RS ( ( ULONG ) 1 << lcd_RS_pin )
#define PINS_CTRL PIN_E | PIN_RW | PIN_RS
#define PINS_DATA (((ULONG)1<
((ULONG)1<#define lcdEstrobeh IOSET0 = PIN_E
#define lcdEstrobel IOCLR0 = PIN_E
#define lcdRWstrobeh IOSET0 = PIN_RW
#define lcdRWstrobel IOCLR0 = PIN_RW
#define lcdRSstrobeh IOSET0 = PIN_RS
#define lcdRSstrobel IOCLR0 = PIN_RS
#define lcdOutputControlBus IODIR0 |= PINS_CTRL
#define lcdInputDataBus IODIR0 &= ~ PINS_DATA
#define lcdOutputDataBus IODIR0 |= PINS_DATA
Andrzej Pawluczuk: Mikrokontrolery ARM (LPC2134) obsługa interfejsu UART w pooling'u -11/24-
void InitLCDEnvir ( void )
{
lcdOutputControlBus ;
lcdOutputDataBus ;
lcdEstrobel ;
IODIR0 |= ( ULONG ) 1 << lcd_BackLight_pin ;
} /* InitLCDEnvir */
static void delay ( ULONG cnt )
{
while ( cnt -- )
{
asm volatile ( "nop" ) ;
} /* while */ ;
} /* delay */
static UCHAR lcdReadDataBus ( void )
{
UCHAR RetData = 0 ;
ULONG PortData ;
/*-------------------------------------------*/
PortData = IOPIN0 ;
if ( PortData & ( ULONG ) 1 << lcd_DB7_pin )
RetData |= 0x08 ;
if ( PortData & ( ULONG ) 1 << lcd_DB6_pin )
RetData |= 0x04 ;
if ( PortData & ( ULONG ) 1 << lcd_DB5_pin )
RetData |= 0x02 ;
if ( PortData & ( ULONG ) 1 << lcd_DB4_pin )
RetData |= 0x01 ;
return ( RetData ) ;
} /* lcdReadDataBus */
static UCHAR LCDInC ( void )
{
UCHAR Status ;
/*-------------------------------------------*/
lcdInputDataBus ;
lcdRSstrobel ;
lcdRWstrobeh ;
delay ( 10 ) ;
lcdEstrobeh ;
delay ( 10 ) ;
Status = lcdReadDataBus ( ) << 4 ;
lcdEstrobel ;
delay ( 10 ) ;
lcdEstrobeh ;
delay ( 10 ) ;
Status |= lcdReadDataBus ( ) ;
lcdEstrobel ;
lcdOutputDataBus ;
return ( Status ) ;
} /* LCDInC */
static void WaitForReady ( void )
{
UCHAR status;
Andrzej Pawluczuk: Mikrokontrolery ARM (LPC2134) obsługa interfejsu UART w pooling'u -12/24-
/*-------------------------------------------*/
do {
status = LCDInC ( ) ;
} while ( status & 0x80 ) ;
} /* WaitForReady */
static void LCDOut4bit ( UCHAR Data )
{
ULONG PortPins = 0 ;
/*-------------------------------------------*/
lcdRWstrobel ;
IOCLR0 = PINS_DATA ;
if ( Data & 0x08 )
PortPins |= ( ULONG ) 1 << lcd_DB7_pin ;
if ( Data & 0x04 )
PortPins |= ( ULONG ) 1 << lcd_DB6_pin ;
if ( Data & 0x02 )
PortPins |= ( ULONG ) 1 << lcd_DB5_pin ;
if ( Data & 0x01 )
PortPins |= ( ULONG ) 1 << lcd_DB4_pin ;
IOSET0 = PortPins ;
lcdEstrobeh ;
delay ( 10 ) ;
lcdEstrobel ;
delay ( 10 ) ;
} /* LCDOut4bit */
static void LCDOutC ( UCHAR Data )
{
WaitForReady ( ) ;
lcdRSstrobel ;
LCDOut4bit ( Data >> 4 ) ;
LCDOut4bit ( Data ) ;
} /* LCDOutC */
static void LCDOutD ( UCHAR Data )
{
WaitForReady ( ) ;
lcdRSstrobeh ;
LCDOut4bit ( Data >> 4 ) ;
LCDOut4bit ( Data ) ;
} /* LCDOutD */
void InitialiseLCD ( void )
{
lcdRSstrobel ;
LCDOut4bit ( 0x3 ) ; /* Select 4-bit interface */
delay ( 100 ) ;
LCDOut4bit ( 0x3 ) ;
delay ( 100 ) ;
LCDOut4bit ( 0x3 ) ;
delay ( 100 ) ;
LCDOutC ( 0x28 ) ; /* 2 lines, 5x8 character matrix */
delay ( 100 ) ;
LCDOutC ( 0x28 ) ; /* 2 lines, 5x8 character matrix */
delay ( 100 ) ;
LCDOutC ( 0x28 ) ; /* 2 lines, 5x8 character matrix */
delay ( 100 ) ;
Andrzej Pawluczuk: Mikrokontrolery ARM (LPC2134) obsługa interfejsu UART w pooling'u -13/24-
LCDOutC ( 0x28 ) ; /* 2 lines, 5x8 character matrix */
delay ( 100 ) ;
LCDOutC ( 0x28 ) ; /* 2 lines, 5x8 character matrix */
delay ( 100 ) ;
LCDOutC ( 0x0C ) ; /* Display ctrl:Disp=ON,Curs/Blnk=OFF */
delay ( 100 ) ;
LCDOutC ( 0x06 ) ; /* Entry mode: Move right, no shift */
delay ( 100 ) ;
LCDOutC ( 0x80 ) ; /* Set DDRAM address counter to 0 */
delay ( 100 ) ;
} /* InitialiseLCD */
void SetCursorPos ( UCHAR ColumnNo ,
UCHAR LineNo )
{
UCHAR Address;
/*-------------------------------------------*/
WaitForReady ( ) ;
Address = ( LineNo * 40 ) + ColumnNo ;
LCDOutC ( 0x80 | ( Address & 0x7F ) ) ;
} /* SetCursorPos */
void ClrScrLCD ( void )
{
WaitForReady ( ) ;
LCDOutC ( 0x01 ) ;
} /* ClrScrLCD */
void HomeLCD ( void )
{
WaitForReady ( ) ;
LCDOutC ( 0x02 ) ;
} /* HomeLCD */
void NewLineLCD ( void )
{
WaitForReady ( ) ;
LCDOutC ( 0xC0 ) ;
} /* NewLineLCD */
void WriteChLCD ( UCHAR Data )
{
LCDOutD ( Data ) ;
} /* WriteChLCD */
void SetCursonOn ( UCHAR BlinkMode )
{
WaitForReady ( ) ;
if ( BlinkMode )
LCDOutC ( 0x0E ) ; // set : display on, cursor on, cursor blink off
else
LCDOutC ( 0x0F ) ; // set : display on, cursor on, cursor blink on
} /* SetCursonOn */
void SetCursonOff ( void )
Andrzej Pawluczuk: Mikrokontrolery ARM (LPC2134) obsługa interfejsu UART w pooling'u -14/24-
{
WaitForReady ( ) ;
LCDOutC ( 0x0C ) ; // set : display on, cursor off, cursor blink off
} /* SetCursonOff */
void WriteTextLCD ( UCHAR * Text )
{
while ( * Text )
WriteChLCD ( * ( Text ++ ) ) ;
} /* WriteTextLCD */
void WriteFlashTextLCD ( const UCHAR * Text )
{
while ( * Text )
WriteChLCD ( * ( Text ++ ) ) ;
} /* WriteFlashTextLCD */
void ClearLine ( UCHAR RowNo )
{
USHORT Loop ;
/*-------------------------------------------*/
SetCursorPos ( 0 , RowNo ) ;
for ( Loop = 0 ; Loop < 16 ; Loop ++ )
WriteChLCD ( ' ' ) ;
SetCursorPos ( 0 , RowNo ) ;
} /* ClearLine */
Moduł SYSTEM (system.h oraz system.c)
(...)
#ifndef _system_
#define _system_
#include "types.h"
// MAM defines
#define MAMCR_OFF 0
#define MAMCR_PART 1
#define MAMCR_FULL 2
#define MAMTIM_CYCLES (((CCLK) + 19999999) / 20000000)
///////////////////////////////////////////////////////////////////////////////
// MEMMAP defines
#define MEMMAP_BBLK 0 // Interrupt Vectors in Boot Block
#define MEMMAP_FLASH 1 // Interrupt Vectors in Flash
#define MEMMAP_SRAM 2 // Interrupt Vectors in SRAM
// PLL setup const
#define FOSC ( 12000000 ) // Master Oscillator Freq.
#define PLL_MUL ( 5 ) // PLL Multiplier
#define PLL_DIV ( 2 ) // PLL Divider
#define CCLK (FOSC * PLL_MUL) // CPU Clock Freq.
#define FCCO (FOSC * PLL_MUL * 2 * PLL_DIV) // CC Osc. Freq.
Andrzej Pawluczuk: Mikrokontrolery ARM (LPC2134) obsługa interfejsu UART w pooling'u -15/24-
#if ( ( FOSC < 10000000 ) || (FOSC > 25000000 ) )
#error Fosc out of range (10MHz-25MHz)
#error correct and recompile
#endif
#if ((CCLK < 10000000) || (CCLK > 60000000))
#error cclk out of range (10MHz-60MHz)
#error correct PLL_MUL and recompile
#endif
#if ((FCCO < 150000000) || (FCCO > 320000000))
#error Fcco out of range (156MHz-320MHz)
#error internal algorithm error
#endif
// Pheripheral Bus Speed Divider
#define PBSD 2
#define PCLK ( CCLK / PBSD ) // Pheripheal Bus Clock Freq.
#if ( ( PBSD != 1 ) && ( PBSD != 2 ) && ( PBSD != 4 ) )
#error Pheripheal Bus Speed Divider (PBSD) illegal value (1, 2, or 4)
#endif
// PLLSTAT Register Bit Definitions
// PLLCON Register Bit Definitions
#define PLLCON_PLLE (1 << 0) // PLL Enable
#define PLLCON_PLLC (1 << 1) // PLL Connect
// PLLCFG Register Bit Definitions
#define PLLCFG_MSEL ((PLL_MUL - 1) << 0) // PLL Multiplier
#define PLLCFG_PSEL ((PLL_DIV - 1) << 5) // PLL Divider
// PLLSTAT Register Bit Definitions
#define PLLSTAT_LOCK (1 << 10) // PLL Lock Status Bit
#define PLLSTAT_PLLE ( ( ULONG ) 1 << 24 )
#define PLLSTAT_PLLC ( ( ULONG ) 1 << 25 )
#define PLLSTAT_PLOCK ( ( ULONG ) 1 << 26 )
// VPBDIV defines & computations
#define VPBDIV_VALUE (PBSD & 0x03) // VPBDIV value
extern void SysInit ( void ) ;
extern ULONG DisableIRQ ( void ) ;
extern ULONG EnableIRQ ( void ) ;
extern ULONG RestoreIRQ ( ULONG /* OldCPSR */ ) ;
#endif
(...)
#include
#include "types.h"
#include "irqservice.h"
#include "system.h"
#define INT_MASK ( I_Bit | F_Bit )
Andrzej Pawluczuk: Mikrokontrolery ARM (LPC2134) obsługa interfejsu UART w pooling'u -16/24-
void SysInit ( void )
{
PINSEL0 = 0 ;
PINSEL1 = 0 ;
PINSEL2 = 0 ;
PLLCFG = PLLCFG_MSEL | PLLCFG_PSEL ;
PLLCON = PLLCON_PLLE ;
PLLFEED = 0xAA ;
PLLFEED = 0x55 ;
while ( ! ( PLLSTAT & PLLSTAT_LOCK ) )
{
} /* while */ ;
PLLCON = PLLCON_PLLE | PLLCON_PLLC ;
PLLFEED = 0xAA ;
PLLFEED = 0x55 ;
MAMTIM = MAMTIM_CYCLES ;
MAMCR = MAMCR_FULL ;
VPBDIV = VPBDIV_VALUE ;
MEMMAP = MEMMAP_FLASH ;
PINSEL0 = 0 ;
PINSEL1 = 0 ;
PINSEL2 = 0 ;
InitIrqSystem ( ) ;
// wdtInit ( ) ;
} /* SysInit */
static inline ULONG __get_cpsr ( void )
{
ULONG RetVal ;
/*-----------------------------------*/
asm volatile ( " mrs %0, cpsr" : "=r" (RetVal) : /* no inputs */ ) ;
return ( RetVal ) ;
} /* __get_cpsr */
static inline void __set_cpsr ( ULONG Val )
{
asm volatile ( " msr cpsr, %0" : /* no outputs */ : "r" (Val) ) ;
} /* __set_cpsr */
ULONG DisableIRQ ( void )
{
ULONG _cpsr ;
/*-----------------------------------*/
_cpsr = __get_cpsr ( ) ;
__set_cpsr ( _cpsr | I_Bit ) ;
return ( _cpsr ) ;
} /* DisableIRQ */
ULONG EnableIRQ ( void )
{
ULONG _cpsr;
/*-----------------------------------*/
_cpsr = __get_cpsr ( ) ;
__set_cpsr ( _cpsr & ~I_Bit ) ;
return ( _cpsr ) ;
} /* EnableIRQ */
Andrzej Pawluczuk: Mikrokontrolery ARM (LPC2134) obsługa interfejsu UART w pooling'u -17/24-
ULONG RestoreIRQ ( ULONG OldCPSR )
{
ULONG _cpsr ;
/*-----------------------------------*/
_cpsr = __get_cpsr ( ) ;
__set_cpsr ( ( _cpsr & ~I_Bit ) | ( OldCPSR & I_Bit ) ) ;
return ( _cpsr ) ;
} /* RestoreIRQ */
Moduł UART1Pool (uart1pool.h oraz uart1pool.c)
(...)
#ifndef _UART1_
#define _UART1_
#include "types.h"
extern void UART1Init( ULONG /* PeriphClk */ ,
UCHAR /* SerialMode */ ,
ULONG /* SerialSpeed */ ) ;
extern void UART1InputReset ( void ) ;
extern void UART1Send ( UCHAR /* Data */ ) ;
extern void UART1SendString ( UCHAR * /* String */ ) ;
extern void UART1SendFlashString ( const UCHAR * /* String */ ) ;
extern void UART1SendNewLine ( void ) ;
extern ULONG UART1DataPresent ( void ) ;
extern UCHAR UART1GetData ( void ) ;
extern void UART1InitEnvir ( void ) ;
extern void UART1Pool ( void ) ;
#endif
(...)
#include
#include "types.h"
#include "uart1pol.h"
#include "serialconst.h"
#define IIR_PEND 0x01
#define IIR_RLS 0x03
#define IIR_RDA 0x02
#define IIR_CTI 0x06
#define IIR_THRE 0x01
#define LSR_RDR 0x01
#define LSR_OE 0x02
#define LSR_PE 0x04
#define LSR_FE 0x08
Andrzej Pawluczuk: Mikrokontrolery ARM (LPC2134) obsługa interfejsu UART w pooling'u -18/24-
#define LSR_BI 0x10
#define LSR_THRE 0x20
#define LSR_TEMT 0x40
#define LSR_RXFE 0x80
#define InpSerialBuffSize 64
typedef struct {
USHORT RdDataPointer ;
USHORT WrDataPointer ;
UCHAR Buffer [ InpSerialBuffSize ] ;
} InpSerialBufferRecT ;
Definicja struktury przewidzianej do utworzenia bufora cyklicznego na
odbierane znaki. Zawiera wskaznik odczytu, zapisu oraz obszar
przeznaczony na odebrane znaki. W poolingowym sprawdzaniu stanu
UART (odbiornika) ewentualnie odczytany znak jest zapisywany do
bufora cyklicznego. Nadawane znaki nie są buforowane, wykonanie
programu jest zawieszane do chwili wysłania ostatniego z ciągu
nadawanych znaków.
static InpSerialBufferRecT UART1InpBuffer ;
Utworzenie zmiennej będącej buforem cyklicznym związanym z
odbiornikiem.
void UART1InputReset ( void )
{
UART1InpBuffer . RdDataPointer = 0 ;
UART1InpBuffer . WrDataPointer = 0 ;
Reset bufora cyklicznego.
} /* UART1InputReset */
void UART1Init( ULONG PeriphClk ,
UCHAR SerialMode ,
ULONG SerialSpeed )
{
Skonfigurowanie układu UART do wymaganej pracy. W parametrach
należy podać częstotliwość sygnału taktującego PCLK (PCLK jest
makrodefinicją utworzoną w pliku system.h), tryb pracy UART jako jedną
z wartości stałych z pliku serialconst.h:
" N81Mode: 8-bitowy tryb transmisji bez bitu parzystości i z
jednym bitem stopu,
" E82Mode: 8-bitowy tryb transmisji z bitem parzystości i z
dwoma bitami stopu.
W parametrze SerialSpeed należy podać żądaną prędkość transmisji.
ULONG Fdiv ;
Andrzej Pawluczuk: Mikrokontrolery ARM (LPC2134) obsługa interfejsu UART w pooling'u -19/24-
ULONG Fmod ;
ULONG LDivider ;
ULONG HDivider ;
/*-------------------------------------------*/
UART1InputReset ( ) ;
Fdiv = ( PeriphClk / 16 ) / SerialSpeed ;
Fmod = ( PeriphClk / 16 ) % SerialSpeed ;
if ( ( Fmod << 1 ) >= SerialSpeed )
Fdiv ++ ;
LDivider = Fdiv % 256 ;
HDivider = Fdiv / 256 ;
Z wartości parametrów wyliczona jest wartość dzielnika dla układu UART
(jako iloraz oraz reszta z dzielenia). Wyliczone wartości będą zapisane do
odpowiednich 8-bitowych rejestrów UART, które wewnętrznie stworzą
16-bitową daną.
U1LCR = 0x80 ;
U1DLL = LDivider ;
U1DLM = HDivider ;
Obliczone wartości są wpisane do odpowiednich rejestrów. Wpis nastaw
podzielnika jest realizowany w trybie DLAB, do którego UART przechodzi
po wpisaniu do rejestru LCR liczby z ustawionym bitem b . Dwa następne
7
wpisy do DLL i DLM są interpretowane jako odpowiednie części
podzielnika. UART po wpisach automatycznie wychodzi z trybu DLAB.
U1LCR = SerialMode ;
Ponowny wpis do rejestru LCR (żaden tryb nie ma w swoim kodzie
ustawionego bitu b ) oznacza odkreślenie trybu transmisji.
7
U1MCR = 0 ;
Wpis do rejestru sterującego liniami modemowymi (UART1 posiada
wszystkie linie modemowe). Przy podłączeniu urządzenia do komputera
PC za pośrednictwem 3-żyłowego przewodu, powyższy wpis jest na
wiwat .
U1FCR = 0x07 ;
Wysterowanie kolejki FIFO wewnątrz UART,
U1IER = 0 ;
i określenie, że UART nie będzie zgłaszał żadnych przerwań.
} /* UART1Init */
void UART1Send ( UCHAR Data )
{
Andrzej Pawluczuk: Mikrokontrolery ARM (LPC2134) obsługa interfejsu UART w pooling'u -20/24-
Funkcja do wysyłania znaku poprzez UART. Przed wysłaniem sprawdzany
jest status, czy nadajnik UART jest opróżniony (by nie nadpisać aktualnie
nadawanego znaku).
while ( ! ( U1LSR & LSR_THRE ) )
{
Pętla oczekująca na opróżnienie rejestru nadajnika,
} /* while */ ;
U1THR = Data ;
który zostaje ponownie zatrudniony do pracy.
} /* UART1Send */
void UART1SendString ( UCHAR * String )
{
Wysłanie ciągu znaków sprowadza się do odpowiedniej liczby wywołań
funkcji wysłania poprzez UART pojedynczego znaku.
while ( * String )
{
UART1Send ( * String ) ;
String ++ ;
} /* while */ ;
} /* UART1SendString */
void UART1SendFlashString ( const UCHAR * String )
{
while ( * String )
{
UART1Send ( * String ) ;
String ++ ;
} /* while */ ;
} /* UART1SendFlashString */
void UART1SendNewLine ( void )
{
UART1Send ( '\r' ) ;
UART1Send ( '\n' ) ;
} /* UART1SendNewLine */
ULONG UART1DataPresent ( void )
{
Funkcja typu boolean przeznaczona do testowania, czy aktualnie w
buforze cyklicznym odbiornika znajdują się znaki.
ULONG Result ;
/*-------------------------------------------*/
Andrzej Pawluczuk: Mikrokontrolery ARM (LPC2134) obsługa interfejsu UART w pooling'u -21/24-
Result = FALSE ;
if ( UART1InpBuffer . RdDataPointer != UART1InpBuffer . WrDataPointer )
{
Result = TRUE ;
} /* if */ ;
return ( Result ) ;
} /* UART1DataPresent */
UCHAR UART1GetData ( void )
{
W przypadku, gdy są dane do odczytu z wejściowego bufora cyklicznego,
funkcja go odczytuje i zwraca jako swój wynik.
UCHAR Data ;
/*-------------------------------------------*/
if ( UART1InpBuffer . RdDataPointer == UART1InpBuffer . WrDataPointer )
{
return ( 0 ) ;
} /* if */ ;
Data = UART1InpBuffer . Buffer [ UART1InpBuffer . RdDataPointer ] ;
UART1InpBuffer . RdDataPointer ++ ;
if ( UART1InpBuffer . RdDataPointer >= InpSerialBuffSize )
UART1InpBuffer . RdDataPointer = 0 ;
return ( Data ) ;
} /* UART1GetData */
void UART1InitEnvir ( void )
{
Użycie UART1 wymaga odpowiedniego skonfigurowania jego środowiska
pracy. Należy ją uruchomić jednorazowo. W wyniku uruchomienia
odpowiednie piny portów zostaną określone jako wyprowadzenia portu
UART pracującego bez linii modemowych. Jednocześnie zostaje
wyzerowany wejściowy bufor cykliczny.
PINSEL0 &= ~ 0x000F0000 ;
PINSEL0 |= 0x00050000 ;
UART1InputReset ( ) ;
} /* UART1InitEnvir */
void UART1Pool ( void )
{
Do nadzorowania wejścia UART należy dość często wywoływać funkcję
do poolingowej jego obsługi. Funkcja sprawdza, czy w UART znajdują się
dane do odczytu oraz ewentualnie zapisuje je do bufora cyklicznego.
UCHAR Data ;
/*-------------------------------------------*/
if ( U1LSR & LSR_RDR )
{
Andrzej Pawluczuk: Mikrokontrolery ARM (LPC2134) obsługa interfejsu UART w pooling'u -22/24-
Jeżeli w rejestrze statusowym jest ustawiony odpowiedni bit oznaczający,
że został odebrany znak,
Data = U1RBR ;
to po jego odczycie
UART1InpBuffer . Buffer [ UART1InpBuffer . WrDataPointer ] = Data ;
UART1InpBuffer . WrDataPointer ++ ;
if ( UART1InpBuffer . WrDataPointer >= InpSerialBuffSize )
UART1InpBuffer . WrDataPointer = 0 ;
jest on zapisany do bufora cyklicznego.
} /* if */ ;
} /* UART1Pool */
Moduł SerialConst (definicja stałych wykorzystanych w
implementacji obsługi UART)
(...)
#ifndef _serialconst_
#define _serialconst_
#include "types.h"
#define N81Mode 0x03
#define E82Mode 0x1F
#define DTRAtConnect 0x01
#define RTSAtConnect 0x02
#define NoParityModeCode 0x00
#define EvenParityModeCode 0x18
#define OddParityModeCode 0x08
#define Bits5ModeCode 0x00
#define Bits6ModeCode 0x01
#define Bits7ModeCode 0x02
#define Bits8ModeCode 0x03
#define Stop1BitCode 0x00
#define Stop2BitCode 0x04
#define Speed600Code 13
#define Speed1200Code 12
#define Speed2400Code 11
#define Speed3600Code 10
#define Speed4800Code 9
#define Speed7200Code 8
#define Speed9600Code 7
#define Speed14400Code 6
#define Speed19200Code 5
#define Speed28800Code 4
#define Speed38400Code 3
#define Speed57600Code 2
#define Speed115200Code 1
Andrzej Pawluczuk: Mikrokontrolery ARM (LPC2134) obsługa interfejsu UART w pooling'u -23/24-
#define RecvDataInterruptEnable 0x01
#define TransmDataInterruptEnable 0x02
#define LineStatusInterruptEnable 0x04
#define ModemStatusInterruptEnable 0x08
#define FIFOEnable 0x01
#define RecvFIFOReset 0x02
#define TrasmFIFOReset 0x04
#define DMAModeSelect 0x08
#define SetLoopbackMode 0x10
#define DCDControlUARTCode 0x80
#define RIControlUARTCode 0x40
#define DSRControlUARTCode 0x20
#define CTSControlUARTCode 0x10
#define DTRControlUARTCode 0x01
#define RTSControlUARTCode 0x02
#define RecvBreakSignalUARTCode 0x10
ULONG SerialSpeedEncoder ( UCHAR /* SpeedCode */ ) ;
#endif
Andrzej Pawluczuk: Mikrokontrolery ARM (LPC2134) obsługa interfejsu UART w pooling'u -24/24-
Uruchomienie powyższego programu w urządzeniu daje przykładowy wynik
(po przyłączeniu wyjścia UART1 poprzez sterownik standardzie RS232 do portu
COM w komputerze PC uruchomionym programem emulatora terminala):
Rys. 2: Ekran emulatora terminala w komputerze
Wyszukiwarka
Podobne podstrony:
2002 p3 answers
arm mat mult ?st q15?
arm biquad ?scade ?1 ?st q31? source
arm conv ?2? source
arm mat mult q15? source
arm fir init q15?
arm biquad ?scade ?1 2x64 q31?
Mikrokontrolery ARM cz1
arm sub ?2?
arm sqrt q15?
arm correlate ?st q15?
arm cos ?2?
arm fir lattice init q31? source
arm fir ?cimate ?st q15? source
arm correlate ?st q15? source
Mikrokontrolery ARM cz10
arm lms norm q15?
Mikrokontrolery ARM cz14
arm pid reset q31?
więcej podobnych podstron