Codebase für LPC1xxx
Codebase für LPC11xx und LPC13xx
Für die Cortex-M0 und -M3 Familien existieren verschiedene Basispakete die als Startausstattung sehr gut geeignet sind. Auf microbuilder.eu findet man eine sehr interessante Version inklusive Dokumentation.
Neben weiteren, interessanten Infos findet man dort eine Beta-Version 0.8 für den LPC1114 vom 14. April 2012 (auch wenn dort 2011 steht!) und eine Beta-Version 1.1.1 für den LPC1343 vom 14. April 2012.
(Achtung: die aktuellste Version findet sich immer unter dem dort auch gezeigten "github"-Link)
Die Original-Dokumentation kann auf der rechten Seite unter "Code Base/Documentation" angewählt werden.
Natürlich können die Funktionen die unter LPC1343 gesammelt werden auch für z.B. den LPC1313 eingesetzt werden, jedoch könnte das Ergebnis beim ansprechen von eigentlich nicht vorhandener Peripherie unvorhersehbar sein.
Der hier folgende Text ist zum gegenwärtigen Zeitpunkt (Januar 2012) im Wesentlichen eine Übersetzung der Seite von microbilder.eu
Allgemeine Informationen zum Aufbau der Code Base
Der Aufbau der Dateien wird am Beispiel für den weiter fortgeschrittenen Stand zur LPC13xx Familie beschrieben, sollte aber weitgehend auch für den LPC1114 anwendbar sein. Die Beispiele der Code-Base beziehen sich auf ein Referenzboard von "microbuilder.eu" das hier verfügbar ist.
Download des im Folgenden beschriebenen Code-Packages als github-Zip hier... immer als aktuellste Version
Ziel ist, auf dem aktuellen Stand aufzusetzen, bereits vorhandene Grundfunktionen zu erweitern und neue hinzuzufügen, Mitarbeit ist herzlich willkommen.
Lizenz
Der Author, microBuilder SARL, hat seine Libs unter eine "modifizierte BSD-Lizenz gestellt", die Nutzung und Modifikation erlaubt, sofern der in jedem File enthaltene Paragraph zur Lizenzbeschreibung erhalten bleibt. Details sind aus jedem beliebigen File der Code Base zu entnehmen.
Unterstütze Peripherieeinheiten
(Stand Januar 2012)
- CPU (vorerst nur auf 72MHz gesetzt)
- ADC (Analog zu Digital Konverter)
- GPIO (Standard Eingänge und Ausgänge)
- I2C (Generischer I2C Code, interrupt betrieben)
- PMU (Power Management, Sleep-Modi)
- PWM (Pulsweiten Modulation)
- SSP (Generischer SSP/SPI Code)
- Systick (Verwendung des 24-bit Systick Timers)
- Timer16 (Die 16-bit Timer)
- Timer32 (Die 32-bit Timer)
- UART (UART code, interrupt betrieben)
- USBCDC (USB / Serial Port Emulation)
- USBHID-ROM (ROM-based USB HID)
- WDT (Watchdog Timer)
Enthaltene Treiber für externe HW
(Stand Januar 2012)
- EEPROM/AT25040 (SPI EEPROM)
- EEPROM/MCP24AA (I2C EEPROM)
- SENSORS/LM75B (I2C Temp Sensor)
- CHIBI - Ein einfacher, Open Source Wireless Stack von Freaklabs für Sensorknoten. In diesem Beispiel für den AT86RF212 Transceiver (868MHz) konfiguriert.
- FATFS - Eine Portierung von Chan's FATFS das bereits FAT32, und einen einfachen MMC Treiber zum lesen von SDHC Karten beinhaltet
- ILI9325 - Treiber für einen auf ILI9325/ILI9328 Controller (8-bit Interface erforderlich) basierten 240x320 TFT LCD.
- ST7565 - Treiber für ein 128x64 pixel Bitmap Display
- SSD1306 - Treiber für ein 128x64 OLED Display (bit-banged SPI mode)
- TCS3414 - TAOS RGB Sensor
- ISL12022M - Temperaturkompensierter RTC
- TSL2561 - TAOS Beleuchtungssensor
- PN532 - 13.56MHz RFID/NFC Transceiver (im moment mit serh limitierter Funktionalität)
- STEPPER - Basis Treiber für einen Bipolar Schrittmotor mit L293D oder SN754410N
Struktur der Code Base
oder "wo finde ich was"
Die LPC1343 Code Base hat - nach einiger Gewöhnungszeit - einen recht einfachen Aufbau:
- Alle bauteilespezifischen Informationen incl. der internen Peripherie befinden sich im Verzeichnis "core".
- Treiber für externe HW ist im Verzeichnis "drivers" zusammengefaßt.
- Die Files zur Projekt- und Systemkonfiguration befinden sich im Root-Verzeichnis.
- Projektfiles für CodeLite (kostenlos) und Rowley Associates Crossworks (kommerziell) stehen im "build" Verzeichnis, und obwohl beide IDEs den gleichen Code verwenden können benutzen sie zum Compilieren nicht die gleiche Toolchain. "Crossworks for Arm" nutze eine eigene GCC Toolchain und einen eigenen Startup Code aber nicht das Makefile im Root-Verzeichnis. Mit CodeLite kann man auch ohne entsprechende Investitionen in HW und SW schon recht angenehm arbeiten
LPC134x.h
Um den Umgang mit der Code Base so einfach wie möglich zu machen wurde ein neues Header-File erzeugt. Obwohl bereits diverse Header-Files für den LPC1343 existieren war der Wunsch die sogenannten "magic-numbers" im Code zu eliminieren. Daher wurde ein "eigenes" erzeugt. Die 134x.h Datei enthält daher für fast jedes Bit das gesetzt oder gelöscht werden kann auch eine entsprechende Definition. Es bedeutet natürlich einen großen Arbeitsaufwand all diese Informationen in ein Header-File zu pakcen, das Resultat ist jedoch ein einfach lesbarer Code, speziell wenn jemand Anderer ihn geschrieben hat.
Was sind diese "Magic Numbers"? Unter "Magic Numbers" versteht man hier den Zugriff auf ein Register ohne "define" also die direkte Angabe einer Zahl in beliebigem Format. Klar, die Eingabe ist kürzer und erzeugt den gleichen Code, aber welche Zeile ist wohl ein halbes Jahr später einfacher zu lesen??
UART_U0LCR = 0x83;
UART_U0LCR = (UART_U0LCR_Word_Length_Select_8Chars |
UART_U0LCR_Stop_Bit_Select_1Bits |
UART_U0LCR_Parity_Disabled |
UART_U0LCR_Break_Control_Disabled |
UART_U0LCR_Divisor_Latch_Access_Enabled);
projectconfig.h
"projectconfig.h" enthält diverse Aufzählungen die innerhalb eines Projektes benutzt werden wie eine Übersicht über die verwendeten Pins, die CPU_Clock, die Zeit für den System-Tick, Baudraten, SSP, USB, ...
Core Peripherie (core/...)
Alle Funktionen zum initialisieren der internen Peripherie sowie ein kleines Beispiel ist im Verzeichnis "core" enthalten.
External Hardware (drivers/...)
Jeden Code, der mit der externen Hardware irgendwie interagiert findet man im Verzeichnis "drivers".
Core/CPU
Die maximale Taktfrequenz des LPC1343 ist 72MHz. Beim Start-Up ist automatisch die max. Taktfrequenz (72MHz), und ein externer Quarz mit 12MHz eingestellt. (Der LPC13xx enthält auch einen internen 12MHz Oszillator, der aber nicht so genau wie ein externer Quarz sein kann. Für USB ist die Genauigkeit definitiv nicht ausreichend.) Um den Stromverbrauch zu minimieren werden alle Pins auf GPIO und "Eingang" gesetzt. Der interne Pull-Up Widerstand ist dabei immer in "pull up" Modus. Dies bedeutet, daß alle Pins nach dem Start der CPU auf "High" gesetzt sind. Um diese Voreinstellungen zu ändern muß cpuInit entsprechend angepaßt werden.
cpuInit
void cpuInit (void)
Initialisiert die System-Taktfrequenz, auf max. Speed (12MHz x 6 = 72MHz)und benutzt einen externen Quarz als Taktquelle. Dies sollte die erste Funktion sein, die ausgeführt wird, da sich die CPU sonst nicht wie erwartet verhalten wird. Alle Pins sind auf GPIO mit aktiviertem internen Pull-up gesetzt.
Übergabeparameter: Keine
#include "core/cpu/cpu.h"
int main(void)
{
cpuInit();
// Enter permanent loop
while(1);
}
cpuGetDeviceID
cpuDeviceID_t cpuGetDeviceID (void)
Liest die CPU-ID aus Übergabeparameter: Keine
Rückgabewert:
cpuDeviceID_LPC1311, cpuDeviceID_LPC1313, cpuDeviceID_LPC1342, cpuDeviceID_LPC1343 oder cpuDeviceID_Unknown
#include "core/cpu/cpu.h"
int main(void)
{
cpuInit();
cpuDeviceID_t id = cpuGetDeviceID();
if (id == cpuDeviceID_LPC1343)
{
// Part is either LPC1343FBD48 or LPC1343FHN33
}
// Enter permanent loop
while(1);
}
Core/ADC
Der LPC1343 enthält einen 8-Kanal, 10-Bit Analog/Digital Wandler (ADC), der zwischen 0 und 3,6V messen kann. (Achtung: Vcc - meist 3,3V - nicht überschreiten. Jeder Kanal kann separat, oder alle 8 Kanäle nacheinander im 'Burst' Mode gewandelt werden. Derzeit ist der 'Burst' Mode nicht in SW umgesetzt.
adcInit
void adcInit (void)
Initialisiert den A/D Konverter und konfiguriert die Kanäle 0..3 für 10-Bit. Übergabeparameter: Keine
Siehe Beispiel für adcRead
adcRead
uint32_t adcRead (uint8_t channelNum)
Diese Funktion startet eine AD-Wandlung für einen einzigen Kanal (0..7) und gibt das Ergebnis zurück (0..1023). Übergabeparameter:
* uint8_t channelNum: Der Kanal [0..7] der abgetastet werden soll
Rückgabewert:
0, wenn ein Überlauf entsteht, ansonsten ein 10-Bit Wert der das Ergebnis der Wandlung enthält.
Warnung: In adcInit werden nur die Kanäle 0..3 als AD-Wandler Input konfiguriert.
#include "core/cpu/cpu.h"
#include "core/adc/adc.h"
void main (void)
{
cpuInit();
adcInit();
uint32_t results = 0;
while(1)
{
// Get A/D conversion results from A/D channel 0
results = adcRead(0);
}
}
Core/GPIO
GPIO (General Purpose Input/Output) bezeichnet einen digitalen Ein-/Ausgang (I/O). JederPin kann unabhängig von Anderen beliebig als Eingang oder als Ausgang konfiguriert werden. Zusätzlich kann jeder GPIO Pin am LPC13xx als externer Interrupt Eingang konfiguriert werden. Wenn sich ein Pegel an einem solchen Pin ändert wird. Zusätzlich besitzt jeder GPIO einen internen Widerstand, der sowohl als Pull-up, als Pull-down oder als Repeater konfiguriert werden kann. Dieser interne Widerstand ist auch abschaltbar. Details hierzu bitte im Datenblatt nachschlagen. Dieser Widerstand sorgt nicht nur für eine Verringerung der erforderlichen Bauteile für so ein System, er erhöht außerdem die Flexibilität, erfordert aber auch mehr Sorgfalt bei der Pinkonfiguration
gpioInit
void gpioInit (void)
Initialisiert GPIO und schaltet den GPIO interrupt handler für alle GPIO Ports ein. Übergabeparameter: Keine
Siehe Beispiel für gpioSetValue
gpioSetDir
void gpioSetDir (uint32_t portNum, uint32_t bitPos, gpioDirection_t dir)
Setzt die Richtung (input/output) für einen bestimmten Port Pin. Übergabeparameter:
* portNum: die gpio Port Nummer [0..3] * bitPos: die Bit Position für den gpio pin [0..11] * dir: die Pin Richtung (gpioDirection_Input or gpioDirection_Output)
Siehe Beispiel für gpioSetValue
gpioSetValue
void gpioSetValue (uint32_t portNum, uint32_t bitPos, uint32_t bitVal)
Setzt einen Wert für einen bestimmten Port Pin (nur relevant, wenn eder Pin als Ausgang konfiguriert wurde). Übergabeparameter:
* portNum: die gpio Port Nummer [0..3] * bitPos: die Bit Position für den gpio pin [0..11] * bitVal: Enthält den neuen Pegen high (1) oder low (0).
#include "core/cpu/cpu.h"
#include "core/gpio/gpio.h"
int main (void)
{
cpuInit();
gpioInit();
// Set GPIO1.8 to output
gpioSetDir(1, 8, gpioDirection_Output);
// Disable the internal pullup/down resistor on P1.8
gpioSetPullup(&IOCON_PIO1_8, gpioPullupMode_Inactive);
// Set GPIO1.8 high
gpioSetValue(1, 8, 1);
while(1);
}
gpioGetValue
uint32_t gpioGetValue (uint32_t portNum, uint32_t bitPos)
Liest einen bestimmten Port Pin aus. Übergabeparameter:
* portNum: die gpio Port Nummer [0..3] * bitPos: die Bit Position für den gpio pin [0..11]
Rückgabewert:
1 wenn der Pin gerade high, oder 0 wenn der Pin gerade low ist. Warnung:
Alle GPIO Pins des LPC1343 haben interne Pull-up/Pull-down widerstände die beliebig konfiguriert werden können. By default, schaltet der LPC1343 nach dem Reset die pull-up Widerstände an den meisten Pins EIN. Hintergrund dieser Vorgehensweise ist, daß der Stromverbrauch geringer ist, wenn die Pins einen definierten Pegel haben, statt zu "floaten". Dies hat jedoch den Nachteil, daß der zurückgelesene Pegel nicht unbedingt mit dem erwarteten Pegen zu tun haben muss.
#include "core/cpu/cpu.h"
#include "core/gpio/gpio.h"
int main (void)
{
cpuInit();
gpioInit();
// Set GPIO1.8 to input
gpioSetDir(1, 8, gpioDirection_Input);
// Disable the internal pullup/down resistor on P1.8
gpioSetPullup (&IOCON_PIO1_8, gpioPullupMode_Inactive);
uint32_t results = 0;
while(1)
{
// Read the current state of GPIO1.8 (1 = high, 0 = low)
results = gpioGetValue(1, 8);
}
}
gpioSetPullup
void gpioSetPullup (volatile uint32_t *ioconReg, gpioPullupMode_t mode)
Alle GPIO Pins des LPC1343 haben interne Pull-up/Pull-down widerstände die beliebig konfiguriert werden können. Diese Funktion kann dazu verwendet werden den Betriebsmodus der integrierten Widerstände auszufählen (inactive, pull-up, pull-down, or repeater) Übergabeparameter:
- *ioconReg: Pointer auf das IOCON Register um den Pin zu wählen (zB. 'IOCON_PIO1_8' für GPIO 1.8, 'IOCON_PIO2_2' für GPIO 2.2, etc.). Achtung: Da dies ein Pointer ist, muß die Adresse (und nicht der Wert) des Registers übergeben werden. Dies wird erreicht in dem ein '&' vor das entsprechende IOCON Register gesetzt wird, z.B.: 'gpioSetPullup(&IOCON_PIO2_2, gpioPullupMode_Inactive);'.
* mode: Betriebsmodus des internen Widerstandes (gpioPullupMode_Inactive, gpioPullupMode_PullDown, gpioPullupMode_PullUp or gpioPullupMode_Repeater).
Warnung:
Der LPC13xx setzt den Pull-up Widerstand direkt nach dem Reset automatisch. ,
Um Schwierigkeiten zu vermeiden wird empfohlen alle Pins immer explizit zu definieren.
#include "core/cpu/cpu.h"
#include "core/gpio/gpio.h"
int main (void)
{
cpuInit();
gpioInit();
// Set GPIO1.8, 1.9, 1.10 and 1.11 to input
gpioSetDir(1, 8, gpioDirection_Input);
gpioSetDir(1, 9, gpioDirection_Input);
gpioSetDir(1, 10, gpioDirection_Input);
gpioSetDir(1, 11, gpioDirection_Input);
// Enable the pull-down resistor on P1.8
gpioSetPullup (&IOCON_PIO1_8, gpioPullupMode_PullDown);
// Enable the pull-up resistor on P1.9
gpioSetPullup (&IOCON_PIO1_9, gpioPullupMode_PullUp);
// Disable the internal resistor resistor on P1.10
gpioSetPullup (&IOCON_PIO1_10, gpioPullupMode_Inactive);
// Set P1.11 to 'Repeater' (remembers the last state explicitly set)
gpioSetPullup (&IOCON_PIO1_11, gpioPullupMode_Repeater);
while(1);
}
gpioSetInterrupt
void gpioSetInterrupt (uint32_t portNum, uint32_t bitPos, gpioInterruptSense_t sense, gpioInterruptEdge_t edge, gpioInterruptEvent_t event)
Jeder GPIO Pin des LPC1343 kann als externe Interrupt Quelle definiert werden. Die Funktion gpioSetInterrupt erlaubt die Festlegung, welcher Pin als Interruptquelle fungieren soll, und spezifiziert die Randbedingungen, unter denen ein Interrupt ausgelöst wird(Pin geht von H==>L oder von L==>H, ...). Abhängig von der portNum, wird der Interrupt durch den PIOINTx_IRQHandler gehandhabt , wobei 'x' der Portnummer entspricht (PIOINT1_IRQHandler wird benutzt wenn der Interrupt z.B. an GPIO Pin 1.8, ausgelöst wird). Übergabeparameter:
* portNum: die gpio Port Nummer [0..3] * bitPos: die Bit Position für den gpio pin [0..11] * sense: Flanken, oder Level-sensitive(gpioInterruptSense_Edge oder gpioInterruptSense_Level). * edge: bei Flanke: Flanken-sensitive als Einfache Flanke (gpioInterruptEdge_Single) oder beide Flanken (gpioInterruptEdge_Double). * event: bei Level:, High oder Low Level (gpioInterruptEvent_ActiveHigh) (gpioInterruptEvent_ActiveLow).
#include "core/cpu/cpu.h"
#include "core/gpio/gpio.h"
int main (void)
{
cpuInit();
gpioInit();
// Set GPIO1.8 to input
gpioSetDir(1, 8, gpioDirection_Input);
// Disable the internal pullup/down resistor on P1.8
gpioSetPullup (&IOCON_PIO1_8, gpioPullupMode_Inactive);
// Setup an interrupt on GPIO1.8
gpioSetInterrupt(1, // Port
8, // Pin
gpioInterruptSense_Edge, // Edge Sensitive
gpioInterruptEdge_Single, // Single Edge
gpioInterruptEvent_ActiveHigh); // Active High
// Enable the interrupt
gpioIntEnable(1, 8);
while (1);
}
gpioIntEnable
void gpioIntEnable (uint32_t portNum, uint32_t bitPos)
Erlaubt einen Interrupt am spezifizierten GPIO-Pin. Übergabeparameter:
* portNum: die gpio Port Nummer [0..3] * bitPos: die Bit Position für den gpio pin [0..11]
Siehe Beispiel für gpioSetInterrupt.
gpioIntDisable
void gpioIntDisable (uint32_t portNum, uint32_t bitPos)
Schaltet einen Interrupt am spezifizierten GPIO-Pin aus. Übergabeparameter:
* portNum: die gpio Port Nummer [0..3] * bitPos: die Bit Position für den gpio pin [0..11]
Siehe Beispiel für gpioSetInterrupt.
gpioIntClear
void gpioIntClear (uint32_t portNum, uint32_t bitPos)
Löscht den Interrupt am spezifizierten Pin. Diese Funktion sollte nur aus der Interrupt-Service Routine aufgerufen werden, wenn der Interrupt aufgetreten ist. Übergabeparameter:
* portNum: die gpio Port Nummer [0..3] * bitPos: die Bit Position für den gpio pin [0..11]
// IRQ Handler for GPIO Port 1
void PIOINT1_IRQHandler(void)
{
uint32_t regVal;
// Check if pin 1.8 raised the interrupt
regVal = gpioIntStatus(1, 8);
if (regVal)
{
// Do Something
...
// Clear the interrupt
gpioIntClear(1, 8);
}
return;
}
Siehe Beispiel für for gpioSetInterrupt to configure an interrupt.
gpioIntStatus
uint32_t gpioIntStatus (uint32_t portNum, uint32_t bitPos)
Liest den Interrupt Status des spezifizierten Port-Pins. Übergabeparameter:
* portNum: die gpio Port Nummer [0..3] * bitPos: die Bit Position für den gpio pin [0..11]
Rückgabewert:
'1' wenn ein Interrupt an diesem Pin aufgetreten ist ansonsten '0'.
Siehe Beispiel für gpioIntClear.
Core/PMU
Konfiguriert die Power Management Unit (PMU) um den Sleep, Deep-sleep und Power-Down Modus. Jeder GPIO Pin kann so konfiguriert werden, um den Prozessor aus dem Sleep Mode aufzuwecken, aber nur ein low-level an Pin 1.4 (WAKEUP) kann den LPC aus dem Power-Down aufwecken.
pmuInit
void pmuInit(void)
Initialisiert die Power Management Unit und Konfiguriert Pin 0.1 so, da er als Wakeup-Quelle für Sleep oder Deep-Sleep Mode fungieren kann. Übergabeparameter: Keine
Notes
Jeder GPIO Pin kann so konfiguriert werden, um den Prozessor aus dem Sleep Mode -- ausgelöst durch pmuSleep oder pmuDeepSleep-- aufzuwecken, aber nur ein low-level an Pin 1.4 (WAKEUP) kann den LPC aus dem Power-Down -- ausgelöst durch pmuPowerDown -- aufwecken.
Im oment ist nur P0.1 als Wakeup Quelle konfiguriert, aber in pmuSleep besteht die Möglichkeit durch auskommentieren beliebige, andere Pins zu wählen, sofern auch die entsprechende GPIO Konfiguration passend gesetzt ist.
Siehe Beispiel für pmuSleep, pmuDeepSleep and pmuPowerDown.
pmuSleep
void pmuSleep(void)
Diese Function versetzt den LPC in den Sleep Mode. Jeder GPIO-Pin kann verwendet werden um den LPC wieder aufzuwecken, der Pin muß entsprechend in pmuInit konfiguriert werden. Übergabeparameter: Keine
#include "core/cpu/cpu.h"
#include "core/pmu/pmu.h"
int main(void)
{
cpuInit();
// Configure wakeup sources before going into sleep/deep-sleep.
// By default, pin 0.1 is configured as wakeup source (falling edge)
pmuInit();
// Enter sleep mode
pmuSleep();
while(1)
{
// Wait for an interrupt to wake the device up
}
}
pmuDeepSleep
void pmuDeepSleep( uint32_t sleepCtrl, uint32_t wakeupSeconds )
Diese Function versetzt den LPC in den Deep-Sleep Mode. AJeder GPIO-Pin kann verwendet werden um den LPC wieder aufzuwecken, der Pin muß entsprechend in pmuInit konfiguriert werden. Der sleepCtrl Parameter wird benötigt umd festzulegen welche Peripherieeinheiten in den Sleep-Mode versetzt werden sollen, siehe SCB_PDSLEEPCFG Register für Details). Optional kann ein Wert ungleich null , in wakeupSeconds bereitgestellt werden, der den Prozessor nach der eingestellten Zeit wieder aufweckt. Dabei wird der 32-bit Timer 0 und Pin 0.1 (CT32B0_MAT2) benutzt.
Übergabeparameter:
* sleepCtrl: hierüber werden die gesetzten Peripherieeinheiten gezielt in Sleep-Mode gesetzt. * wakeupSeconds: Ist dieser Wert größer 0 wird der Prozessor automatisch bach dieser Zeit in Sekunden wieder aufgeweckt.
#include "core/cpu/cpu.h"
#include "core/pmu/pmu.h"
int main(void)
{
cpuInit();
uint32_t pmuRegVal;
// Configure wakeup sources before going into sleep/deep-sleep.
// By default, pin 0.1 is configured as wakeup source (falling edge)
pmuInit();
// Inidicate which peripherals should be disabled in deep-sleep
pmuRegVal = SCB_PDSLEEPCFG_IRCOUT_PD |
SCB_PDSLEEPCFG_IRC_PD |
SCB_PDSLEEPCFG_FLASH_PD |
SCB_PDSLEEPCFG_USBPLL_PD |
SCB_PDSLEEPCFG_SYSPLL_PD |
SCB_PDSLEEPCFG_SYSOSC_PD |
SCB_PDSLEEPCFG_ADC_PD |
SCB_PDSLEEPCFG_BOD_PD;
// Enter deep sleep mode and wakeup after 10 seconds
pmuDeepSleep(pmuRegVal, 10);
while(1)
{
}
}
pmuPowerDown
void pmuPowerDown( void )
Diese Function konfiguriert das PMU Control Register so, daß der LPC in den deep power-down mode geht. Achtung: Alle Register außer der vier Register (PMU_GPREG0..3) verlieren ihren Inhalt während der Prozessor im Deep-Power Down Mode ist. die 3,3V dürfen dazu nicht wegfallen Übergabeparameter: Keine
Warnung:
Der LPC kann NUR durch einen Low-level an Pin P1.4 (WAKEUP aufgeweckt werden).
#include "core/cpu/cpu.h"
#include "core/pmu/pmu.h"
int main(void)
{
cpuInit();
pmuInit();
// Enter power-down mode
pmuPowerDown();
while(1)
{
// Device was woken up by WAKEUP pin
}
}
Core/SSP
Generischer Code für SSP/SPI Kommunikation. Der SSP Block wird als SPI Master Mode initialisiert
sspInit
void sspInit (uint32_t portNum, sspClockPolarity_t polarity, sspClockPhase_t phase)
Initialisiert den SSP Port. By default, SSP wird als SPI frame-format mit 8-bit Data initialisiert. Pin 2.11 wird als serial clock (SCK) verwendet, und SSEL (0.2) ist als GPIO initialisiert, um manuell den SPI Port ein- bzw. Auszuschalten Überlauf und Timeout Interrupts sind beide ein. Übergabeparameter:
* portNum: Port Number. ( Standardmäßig 0, es sei denn auf einem LPC1313/1.) * polarity: Clock High (sspClockPolarity_High) oder Low (sspClockPolarity_Low)als inaktiven Pegel. * phase: Bit Start mit steigender Flanke (sspClockPhase_RisingEdge) oder mit fallender Flanke sspClockPhase_FallingEdge) bei Pegelwechsel von SCK.
Notes
sspSelect() und sspDeselect() macros wurden ssp.h definiert, um SSEL kontrollieren zu können, ohne deß der dafür definierte Pin bekannt ist line Siehe Beispiel für sspSend
sspSend
void sspSend (uint32_t portNum, uint8_t *buf, uint32_t length)
Sendet einen Datenblock an den SSP Port Übergabeparameter:
* portNum: Port Number. ( Standardmäßig 0, es sei denn auf einem LPC1313/1.) * *buf: Pointer auf den Datenpuffer * length: Block Länge des Datenpuffers
#include "core/cpu/cpu.h"
#include "core/ssp/ssp.h"
#define SSP_FIFOSIZE 8
int main(void)
{
cpuInit();
sspInit(0, sspClockPolarity_High, sspClockPhase_RisingEdge);
uint8_t request[SSP_FIFOSIZE];
uint8_t response[SSP_FIFOSIZE];
// Send 0x9C to the slave device and wait for a response
// Fill request buffer
request[0] = 0x80 | 0x1C;
// Enable CS line
ssp0Select();
// Send the 'request' data (1 byte)
sspSend(0, (uint8_t *)&request, 1);
// Wait for the response (1 byte)
sspReceive(0, (uint8_t *)&response, 1);
// Disable CS line
ssp0Deselect();
}
sspReceive
void sspReceive(uint32_t portNum, uint8_t *buf, uint32_t length)
Empfängt einen Datenblock an den SSP Port Übergabeparameter:
* portNum: Port Number. ( Standardmäßig 0, es sei denn auf einem LPC1313/1.) * *buf: Pointer auf den Datenpuffer * length: Block Länge des Datenpuffers
Siehe Beispiel für sspSend
Core/Systick
Steuert den 24-bit 'system tick' Timer, der sowohl als normaler Timer, alsauch als System-Timer für ein real-time Betriebssystem (FreeRTOS, Crossworks CTL, etc.) verwendet werden kann.
systickInit
void systickInit (uint32_t delayMs)
Initialisiert den Systick Timer in Millisekunden (typischer Wert = 10ms). Dies führt alle z.B. 10ms zu einem Systtick Interrupt und dazu, daß eine unsigned 32-Bit Variable mit dem Namen "msTicks" um 1 hochgezählt wird wenn der Interrupt ausgelöst wird. Übergabeparameter:
* delayMs: Indicates the length of time in millaseconds between each system 'tick'.
Siehe Beispiel für systickDelay.
systickDelay
void systickDelay (uint32_t delayTicks)
Führt zu einem den Prozessor blockierenden Wartezeit von einer spezifizierten Anzahl an Systick Timer Ticks. Die Länge der Pause hängt von der in der systickInit Function definierten Interruptzeit ab. Übergabeparameter:
* delayTicks: The number of systick ticks to wait.
#include "core/cpu/cpu.h"
#include "core/systick/systick.h"
int main (void)
{
// Initialise the cpu
cpuInit();
// Initialise the systick timer with one tick every 10 millaseconds
systickInit(10);
while(1)
{
// Wait 15 ticks on the systick timer (meaning 150ms)
systickDelay(15);
// Do something ...
}
}
Core/Timer16
Steuert alle 16-Bit Timers auf dem LPC1343. Achtung: bei 72MHz deckt ein 16-Bit Timer nur eine Zeit von knapp 0.91mS (or 910uS) ab:
1 mS = CFG_CPU_CCLK / 1000
= 72000000 / 1000 = 72000 'ticks'
Der Maximalwert eines 16-Bit Timers ist 0xFFFF (65535) also 0.910208ms.
timer16Init
void timer16Init(uint8_t timerNum, uint16_t timerInterval)
Initialisiert einen 16-bit timer mit seiner Interruptzeit. Jedes mal, wenn der Zeiraum abgelaufen ist wird der Timer-Interrupt ausgelöst, und die Zählervariable um eins hochgezählt. (z.B. mit Timer CT16B0, wird der 'timer16_0_counter' Inkrementiert). Übergabeparameter:
* timerNum: Der 16-Bit Timer der initialisiert werden soll [0..1] * timerInterval: Die Anzahl an Takt-'ticks' zwischen den Interrupts [0..65534]
Warnung
Vorsicht bei der Konfiguration der Timer, da die Pins mehrfach mit anderer Peripherie gemultiplext werden, je nach Initialisierung.Diese Funktion dient nur der besseren Veranschaulichung und muß unbedingt an die jeweiligen Randbedingungen angepaßt werden.
#include "/core/cpu/cpu.h"
#include "/core/timer16/timer16.h"
// Instantiated in timer16.c
extern volatile uint32_t timer16_0_counter;
int main(void)
{
cpuInit();
// Initialise timer0 with a delay of 0xFFFF, which will cause the
// timer interrupt to fire every 65535 ticks and increment
// timer16_0_counter by 1
timer16Init(0, 0xFFFF);
// Enable the timer
timer16Enable(0);
// At this point timer16_0_counter should start incrementing by 1
// every 65535 ticks
while(1)
{
// If the timer has been fired 10 times, disabled the timer
if (timer16_0_counter == 10)
{
timer16Disable(0);
}
}
}
timer16DelayTicks
void timer16DelayTicks(uint8_t timerNum, uint16_t delayInTicks)
Führt zu einer blockierenden Pause für die definierte Anzahl an Takt-ticks. Übergabeparameter:
* timerNum: Der 16-Bit Timer der initialisiert werden soll [0..1] * delayInTicks: Anzahl an Takt ticks die pausiert werden soll [0..65534]
Notes
Die genaue Zeitdauer der Pause hängt von der Taktrate des System-Taktes ab.
#include "/core/cpu/cpu.h"
#include "/core/timer16/timer16.h"
int main(void)
{
cpuInit();
// Initialise timer 0 ... delay is provided but not used here
timer16Init(0, 0xFFFF);
// Enable the timer
timer16Enable(0);
while(1)
{
// Cause blocking delay for 36000 ticks (0.5mS @ 72MHz)
// Note: The delay must be 65534 or less (16-bit value)
timer16DelayTicks(0, 36000);
}
}
timer16DelayUS
void timer16DelayUS(uint8_t timerNum, uint16_t delayInUS)
Führt zu einer blockierenden Pause für die definierte Anzahl an Mikrosecunden. Übergabeparameter:
* timerNum: Der betreffende 16-Bit Timer [0..1] * delayInUS: Anzahl der Mikrosekonden, die gewartet werden soll
Warnung
Die maximale Wartezeit bei 72MHz beträgt 910uS (0xFFFF / 72 = 910), or 0.91ms
#include "/core/cpu/cpu.h"
#include "/core/timer16/timer16.h"
int main(void)
{
cpuInit();
// Initialise timer 0 ... delay is provided but not used here
timer16Init(0, 0xFFFF);
// Enable the timer
timer16Enable(0);
while(1)
{
// Cause blocking delay for 500 microseconds (0.5mS)
timer16DelayUS(0, 500);
}
}
timer16Enable
void timer16Enable(uint8_t timerNum)
Schaltet den spezifizierten Timer ein (erlaubt die Auslösung der konfigurierten Interrupts) Übergabeparameter:
* timerNum: Der betreffende 16-Bit Timer [0..1]
Siehe Beispiel für timer16Init
void timer16Disable(uint8_t timerNum)
Schaltet den spezifizierten Timer aus (verbietet die Auslösung der konfigurierten Interrupts) Übergabeparameter:
* timerNum: Der betreffende 16-Bit Timer [0..1]
Siehe Beispiel für timer16Init
timer16Reset
void timer16Reset(uint8_t timerNum)
Setzt den spezifizierten Timer zurück. Übergabeparameter:
* timerNum: The 16-bit timer to reset [0..1]
Core/Timer32
Steuert alle 32-Bit Timers auf dem LPC1343. Achtung: der 32-bit timers ermöglicht einen deutlich längeren Timerinterrupt als der 16-Bit Timer. z.B.
1 mS = CFG_CPU_CCLK / 1000
= 72000000 / 1000 = 72000 'ticks'
Der Maximalwert eines 32-Bit Timers ist, 0xFFFFFFFF (4,294,967,295), gleichbedeutend mit 59652ms (etwas weniger als eine Minute, im Vergleich ~0.91ms mit einem 16 Bit Timer @ 72MHz).
Sowohl die 16-Bit, alsauch die 32-Bit Timer können in verbindung mit einem externen Pin eingesetzt werden. z.B. setzen/löschen eines Pins, wenn ein "Match" eintritt. Jeses Matchregisters jedes Timers kann auch als PWM Register verwendet werden und ein entsprechendes PWM-Verhältnis ausgeben zu können.
timer32Init
void timer32Init(uint8_t timerNum, uint32_t timerInterval)
Initialisiert einen 32-bit timer mit seiner Interruptzeit. Jedes mal, wenn der Zeiraum abgelaufen ist wird der Timer-Interrupt ausgelöst, und die Zählervariable um eins hochgezählt. (z.B. mit Timer CT16B0, wird der 'timer16_0_counter' Inkrementiert). Übergabeparameter:
* timerNum: Der 32-Bit Timer der initialisiert werden soll [0..1] * timerInterval: Die Anzahl an Takt-'ticks' zwischen den Interrupts [0..4,294,967,294]
Warnung: Vorsicht bei der Konfiguration der Timer, da die Pins mehrfach mit anderer Peripherie gemultiplext werden, je nach Initialisierung.Diese Funktion dient nur der besseren Veranschaulichung und muß unbedingt an die jeweiligen Randbedingungen angepaßt werden.
#include "/core/cpu/cpu.h"
#include "/core/timer32/timer32.h"
// Instantiated in timer32.h
extern volatile uint32_t timer32_0_counter;
int main(void)
{
cpuInit();
// Initialise timer0 with a delay of 72000, which will cause the
// timer interrupt to fire every 1mS @ 72MHz and increment
// timer32_0_counter by 1
timer32Init(0, 72000);
// Enable the timer
timer32Enable(0);
// At this point timer32_0_counter should start incrementing by 1
// every 72000 ticks
while(1)
{
// If the timer has been fired 10 times, disabled the timer
if (timer32_0_counter == 10)
{
timer32Disable(0);
}
}
}
timer32Delay
void timer32Delay(uint8_t timerNum, uint32_t delay)
Führt zu einer blockierenden Pause für die definierte Anzahl an Takt-ticks. Übergabeparameter:
* timerNum: Der 16-Bit Timer der initialisiert werden soll [0..1] * delayInTicks: Anzahl an Takt ticks die pausiert werden soll
Notes
Die genaue Zeitdauer der Pause hängt von der Taktrate des System-Taktes ab.
Warning
Die max. delay-Zeit hängt von 'timerInterval' Wert ab, der bei der Timer initialisierung verwendet wird (siehe timer32Init).
#include "/core/cpu/cpu.h"
#include "/core/timer32/timer32.h"
int main(void)
{
cpuInit();
// Initialise timer 0 with 1 millisecond 'ticks'
timer32Init(0, TIMER32_CCLK_1MS);
// Enable the timer
timer32Enable(0);
while(1)
{
// Cause a blocking delay for 1.5 seconds (1500 milliseconds)
timer32Delay(0, TIMER32_DELAY_1MS * 1500);
}
}
timer32Enable
void timer32Enable(uint8_t timerNum)
Schaltet den spezifizierten Timer ein (erlaubt die Auslösung der konfigurierten Interrupts) Übergabeparameter:
* timerNum: Der betreffende 32-Bit Timer [0..1]
Siehe Beispiel für timer32Init
timer32Disable
void timer32Disable(uint8_t timerNum)
Schaltet den spezifizierten Timer aus (verbietet die Auslösung der konfigurierten Interrupts) Übergabeparameter:
* timerNum: Der betreffende 32-Bit Timer [0..1]
Siehe Beispiel für timer32Init
timer32Reset
void timer32Reset(uint8_t timerNum)
Setzt den spezifizierten Timer zurück. Übergabeparameter:
* timerNum: Der betreffende 32-Bit Timer [0..1]
Core/UART
Ermöglicht es einfache Teste über RS232, USB oder FTDI232RL zu senden oder zu empfangen. Jeder eingehende Text wird in einem FIFO gespeichert sodaß Datenverlust nicht auftreten sollte.
uart_pcb_t
uart_pcb_t *uartGetPCB ()
Liefert einen Pointer auf den Protokollblock des UART's. Damit kann der Status des UART ermittelt werden, und damit ob der UART initialisiert wurde, ob auf Daten gewartet oder gerade gesendet wird und um eine Referenz auf den Empfangs-FIFO zu erhalten.
Übergabeparameter: Keine
// Make sure that UART is initialised
uart_pcb_t *pcb = uartGetPCB();
if (!pcb->initialised)
{
uartInit(CFG_UART_BAUDRATE);
}
uartInit
void uartInit (uint32_t baudrate)
Initialisiert den UART mit einer spezifischen Baud-Rate. Übergabeparameter:
* baudRate: Die Baud-Rate, mit der der UART konfiguriert werden soll (z.B. '57600').
#include "core/cpu/cpu.h"
#include "core/uart/uart.h"
#define UARTBUFFERSIZE 5
int main(void)
{
cpuInit();
uartInit(57600);
uint8_t uartBuffer[UARTBUFFERSIZE] = { 'T', 'e', 's', 't', '\n' };
while(1)
{
// Constantly send contents of uartBuffer
uartSend((uint8_t *)uartBuffer, UARTBUFFERSIZE);
}
}
uartSend
void uartSend (uint8_t *bufferPtr, uint32_t length)
Sendet den Inhalt des Puffers über den UART. Übergabeparameter:
* *bufferPtr: Pointer zum Text Buffer * length: Die Größe des Text Buffers
Siehe Beispiel für uartInit
uartSendByte
void uartSendByte (uint8_t byte)
Schickt ein einzelnes Byte an den UART. Übergabeparameter:
* byte: Das zu sendende Byte
// Send 0xFF over UART
uartSendByte(0xFF);
// Send 'B' over UART (note single quotes)
uartSendByte('B');
uartRxBufferInit
void uartRxBufferInit ()
Initialisiert den RX FIFO buffer. Übergabeparameter: Keine
No example current available.
uartRxBufferRead
uint8_t uartRxBufferRead ()
Liest ein Byte aus dem RX Buffer. Diese Funktion liefert ein Byte zurück, das durch den Array Index spezifiziert wird. Erreicht der Pointer die max. Buddergröße, beginnt er wieder bei '0'. Übergabeparameter: Keine
Siehe Beispiel für uartRxBufferWrite.
uartRxBufferWrite
void uartRxBufferWrite(uint8_t data)
Schreibt ein Byte in den RX Buffer.
Note: Normalerweise ist es nicht notwendig diese Funktion zu benutzen, da alle eingehenden Daten über den UART Interrupt laufen, und jedes Byte in den RX-Buffer geschrieben wird. Übergabeparameter:
* uint8_t data: Byte, das in den RX Buffer geschrieben werden soll.
#include "core/cpu/cpu.h"
#include "core/uart/uart.h"
int main(void)
{
cpuInit();
uartInit(57600);
// Add 0xFF to the RX buffer
uartRxBufferWrite(0xFF);
// Check if the buffer is empty (it shouldn't be!)
while (uartRxBufferDataPending())
{
// Retrieve the first available character in the buffer
uint8_t c = uartRxBufferRead();
}
...
}
uartRxBufferClearFIFO
void uartRxBufferClearFIFO ()
Löscht die RX und TX Pointer und setzt die Längen auf Null. Übergabeparameter: Keine
No example currently available.
uartRxBufferDataPending
void uartRxBufferDataPending()
Stellt fest, ob Daten im FIFO sind. Wenn ein odermehr Bytes im FIFO enthalten sind, wird eine '1' zurückgeliefert Ist der Puffer leern wird eine '0' zurückgeliefert. Übergabeparameter: Keine
Siehe das Beispiel für uartRxBufferWrite.
Core/USBHID-ROM
Der LPC1343 enthält eine ROM-basierte Unterstützung für HID (Human Interface Device) und MSCD (Mass Storage Device) was einem eine relativ einfache Möglichkeit liefert USB Klassen schnell und effizient zu implementieren. Eine einfache HID implementierung ist in der Code-Base enthaltenund beinhaltet die Basis-Kommunikation zwischen dem LPC1343 und einem PC or USB-Host Device. In diesem Beispiel wird das Device so konfiguriert, daß "1-Byte! telegramme geschickt werden können. Achtung: dieses Beispiel ist auf das bei microbuilder.eu verfügbare LPC1343 Reference Board abgestimmt.
Dieser ROM-basierte HID Driver macht es wirklich außergewöhnlich bequem, ist aber weniger flexibel als ein vollständig SW-basierter USB/HID Stack. Der Hauptunterschied ist, daß man hier auf einen "single Report" limitiert ist. Ein vollständig SW-basierter Stack ist auf der NXP-Website verfügbar. Ein möglicher Kompromiß zwischen Aufwand und flexibilität ist, daß z.B. immer zwei oder mehre Byte-Reports verschickt werden, wobei das erste Byte als eine adt "Komando-ID" bestimmt, wie die nachfolgenden Bytes interpretiert werden sollen. Speicher-Einschränkung: Der ROM-basierte HID Treiber verwendet 0x10000050 to 0x10000180 des On-Chip RAM, was bedeutet, daß im Linkter entsprechend eingestellt werden muß , daß diese Sektion nicht verwendet werden darf.
usbHIDInit
void usbHIDInit (void)
Initialisiert das Device für USB HID Support und versucht einen Verbindungsaufbau zum Host. Das Device ist als 1 Byte Report konfiguriert.
Übergabeparameter: Keine
#include "core/cpu/cpu.h"
#include "core/usbhid-rom/usbhid.h"
#include "core/gpio/gpio.h"
int main(void)
{
cpuInit();
// Set GPIO2.10 (LED) as output
gpioSetDir(2, 10, gpioDirection_Output);
// Disable LED (set high)
gpioSetValue (2, 10, 1);
// Initialise and connect USB
usbHIDInit();
// The device should enumerate on the PC, and
// the LED on 2.10 can be enabled by sending 0x01
while (1)
{
}
}
usbHIDGetInReport
void usbHIDGetInReport (uint8_t src[], uint32_t length)
Setzt die HID im Report (vom LPC1343 zum USB host). Übergabeparameter:
* src[]: Ein Byte-Array für die Report Daten * length: Länge des src
Warnung
The signature for this method (uint8_t src[], uint32_t length) should not be modified, and this method should never be called directly. All interrupts and report exchanges are handled by the rom-based drivers. The only thing that should be modified in these methods is the code inside them that either generates or handles the appropriate byte data.
See the example for usbHIDInit
usbHIDSetOutReport
void usbHIDSetOutReport (uint8_t dst[], uint32_t length)
Sezt den HID-out Report (Vom USB-Host zum LPC1343). Übergabeparameter:
* src[]: Ein Byte-Array für die Report Daten * length: Länge des src
Warnung
The signature for this method (uint8_t dst[], uint32_t length) should not be modified, and this method should never be called directly. All interrupts and report exchanges are handled by the rom-based drivers. The only thing that should be modified in these methods is the code inside them that either generates or handles the appropriate byte data.
See the example for usbHIDInit
Core/WDT
Der LPC1343 enthält einen Watchdog-Timer der benutzt werden kann das Sytem am laufen zu halten. Damit wird festgestellt, ob der LPC abgestürzt ist, oder nicht. Der 'Watchdog' ist so konfiguriert, daß er alle 'x' Ticks des System-Taktes getriggert werden muss. Wenn dies nicht stattfindet, können verschiedene Aktionen ausgelöst werden, (z.B. System-Reset, oder die Auslösung eines Interrupts). Die Grundeinstellung des in der Code-Base vorhandenen Codes setzt den Watchdog auf eine Togglerate von 250kHz, also einmal alle 250.000 Taktzyklen, und hier wird nur der WDT_IRQHandler ausgelöst.
wdtInit
void wdtInit (void)
Initialisiert den Watchdog Timer und den interrupt.
Übergabeparameter: Keine
#include "core/cpu/cpu.h"
#include "core/wdt/wdt.h"
int main(void)
{
cpuInit();
wdtInit();
// Pat the watchdog to start it
wdtFeed();
while(1)
{
// Keep the watchdog happy by regularly feeding it
wdtFeed();
// Any delay here > 250,000 ticks (~3.5mS @ 72MHz)
// will cause the watchdog to raise an interrupt, which
// will be handled by WDT_IRQHandler
}
}
wdtFeed
void wdtFeed (void)
Toggelt den Watchdog um einen Timeout zu verhindern.
Übergabeparameter: Keine
Siehe Beispiel für wdtInit