Grafisk display + seriekommunika3on (USART) Ulf Assarsson Läromoment: USART Grundläggande C-programmering del 2 Pekare portadressering med structs structs med funk.onspekare Kopplat.ll: Arbetsbok avsni5: 5 graphicdisplay 6 seriekommunika.on Lab 3 Läsanvisningar: Översiktligt: STM32F407 reference manual s: 951-1002
Översikt USART-porten Grundläggande C-programmering Pekare structs Pekare.ll Sammansa5a datatyper (struct) Dvs pilnota.on: structpekare->medlem; Portar Funk.oner structs med funk.onspekare som klassmetoder vid objektorienterad programmering 2
USART USART - Universal synchronous asynchronous receiver transmitter Eterm8 / CodeLite / CoolTerm USB -> RS232-chip (FTDI) USART-krets inbyggt i cortex-m4 Virtuell COM-port USB <--> USB Dator Port: 0x40011000-0x4001101a
USB -> RS232-chip (.llverkat av FTDI chip ) USART-krets inbyggt i cortex-m4 USB TX/ RX Port: 0x40011000-0x4001101a
Programmering av inbyggda system Seriekommunikation, punkt till punkt Central Processing Unit Serial to parallel conversion Receive Data: RX ARM cortex-m4 Parallel to serial conversion USART-krets Transmit Data: TX Central Processing Unit Serial to parallel conversion Transceiver Receive Transmit Transceiver Receive Transmit Parallel to serial conversion Serial transmission Seriekommunikation 5
Programmering av inbyggda system Sändare Data buss Mottagare Data buss Control CS OE Data Register Control OE Data Register E Clock Serial data out Shift Register TxD Serial data in RxD Clock Shift Register Sändare och mottagares klockor går i samma takt Seriekommunikation 6
Programmering av inbyggda system överföring av tecknet z Tecknet z representeras av bitmönstret 0111 1010 (ASCIItecken). S T A R T P A R I T E T S T O P P idle 0 0 1 0 1 1 1 1 0 0 1 idle z minst signifikanta bit först Seriekommunikation 7
Läsa / skriva via USART-porten #define USART_DATA_REG ( (unsigned short *) 0x40011004 ) #define USART_SR_REG ( (unsigned short *) 0x40011000 ) void outchar( char c ) // write character to usart1 *USART_DATA_REG = (unsigned short) c; while (( *USART_SR_REG & 0x80)==0); if( c == '\n') // line feed (0x0a) outchar('\r'); // carriage return (0x0d) USART_SR_REG bit 7 (TXE): 0: Dataregistrets sändardel är upptagen med en överföring 1: Dataregistrets sändardel är klar a5 användas char tstchar( void ) if( (*USART_SR_REG & 0x20)==0) return 0; return (char) *USART_DATA_REG; USART_SR_REG bit 5 (RXNE): 0: Inget ny5 innehåll i USART_DATA_REG sedan senaste läsningen 1: Ny5 innehåll finns i USART_DATA_REG. Introduk.on C-programmering 8
USART Stödjer LIN-protokollet (Local Interconnect Network) Volvo, Audi, BMW Smartcardläsare (bankdosa m. usb-port) CAN-bussprotokollet (Controller Area Network) IR-tranceivers
The LIN protocol, started in 1998 LIN Local Interconnection network predecessor: VOLCANO Lite Cooperation between partners: Freescale, VOLVO CAR, BMW, AUDI, Volkswagen, Daimler- Chrysler Mentor Graphics (former: Volcano Communication Technology) Objectives: Low cost, modest performance and safety requirements, flexible system architecture
LIN target applications Roof: (high amount of wiring) Rain Sensor, Light Sensor, Light Control, Sun Roof (Rain Sensor needs to be interrogated every 10-20ms) Door/window/seat: Mirror,Central ECU, Mirror, Switch, Window Lift, Seat Control Switch, Door Lock, etc. Steering Wheel: (very many controls are going to be positioned on the steering wheel) Climate: many Small Motors Control Panel Cruise Control, Wiper, Turning Light, Optional: Climate Control, Radio, Telephone, etc. Seat: many Seat Position Motors, Occupancy Sensor, Control Panel
Pekare - översikt Dvs, om a s värde är en adress, så är *a vad adressen innehåller. &a -> Adress till variabel a. Dvs minnesadress som a är lagrat i. a -> variabelns värde (t ex int, float eller en adress om a är pekarvaribel) *a -> Vad variabel a pekar på (här måste a's värde vara en giltig adress och a måste vara av typen pekare). a s värde är en adress till en annan variabel eller port. Vi hämtar värdet för den variabeln/porten. Exempel för pekarvariabel p: Adress för c: 0x2001bff3 118 ('v')... *p är värdet som p pekar på, dvs 'v' char c = 'v'; char* p = &c; *p == c; Adress för p: 0x2001c026 p s värde 0x2001bff3... Ökande adresser 12
Pekare Pekarens värde är en adress. Pekarens typ berä5ar hur man tolkar bitarna som finns på adressen. // array av chars char str[] = "apa"; Vi hämtar värdet som ligger på adressen som ligger i p. // pekare till char char* p = str; // == &str[0] == &(str[0]) *p; // 'a' *p = 'b'; MOV R0, #'b LDR R1, p STRB R0, [R1] - skriv.ll *p LDR R0, =str LDR R1, =p STR r0, [R1] LDR R0, p LDRB R0, [R0] - läs *p Pekare och Arrayer/VK 13
Dereferera När vi derefererar en pekare så hämtar vi objektet som ligger på adressen. Antalet bytes vi läser beror på typen Tolkningen av bitarna beror på typen signed char 8 bitar 1111 1111 char str[] = "apa"; char* p = &str[0]; // = &(str[0]) char s = *p; unsigned char -1 255 char är e5 8-bits värde, dvs e5 8-bits tal. E5 tal kan motsvara en bokstav via ASCII-tabellen. Pekare och Arrayer/VK 14
Operatorer på pekare #include <stdio.h> int main() char a, b, *p; a = 'v'; b = a; p = &a; Deklara.on av pekare Adressen av... printf("b = %c, p = 0x%p (%c) \n", b, p, *p); a = 'k'; printf("b = %c, p = 0x%p (%c) \n", b, p, *p); Dereferering Utskit: b = v, p = 0x0027F7C3 (v) b = v, p = 0x0027F7C3 (k) Pekare och Arrayer/VK 15
Asterisken (*) betyder I deklara.oner Pekartyp Som operator Dereferens ( av-referera ) char *p; char* p; void foo(int *pi); char a = *p; *p = 'b'; Pekare och Arrayer/VK 16
C vs Assembler C Assembler Betyder int v; v:.space 4 skapa adress för v &v; LDR R0, =v v s adress (t ex 0x2001c010) v; int *v; LDR R0, v v s värde t ex 5 eller om v pekare: 0x2001c004 *v; LDR R0, [v] värdet som ligger på Hämtar det som v pekar på men finns inte på m4 adressen som ligger i v. så man får skriva: T ex: v = 0x2001c004 LDR R7, v Ladda v s värde (R7=0x2001c004) LDR R0, [R7] Hämta innehållet på adress 0x2001c004 (4 bytes, t ex 6). 17
Aritme.k på pekare char *kurs = "Maskinorienterad Programmering"; *kurs; *(kurs+2); kurs++; kurs +=4; // 'M // 's // kurs pekar på 'a // kurs pekar på 'n' Man ökar p med (n * typstorlek) 18
Sammansa5a datatyper (structs) En så kallad struct (från eng. structure) Har en/flera medlemmar. Medlemmarna kan vara av bas-typ (t ex int, float, char, double) egendefinerad typ (t ex en annan struct). Pekare (även.ll funk.oner och samma struct) Fortsä5ning Pekare/VK 19
Användning av struct #include <stdio.h> char* kursnamn = Maskinorienterad Programmering"; struct Course char* name; float credits; int numberofparticipants; ; int main() struct Course mop; mop.name = kursnamn; mop.credits = 7.5f; mop.numberofparticipants = 110; Defini.on av strukturen Deklara.on av variabeln mop Access.ll medlemmar via.-operatorn return 0; Fortsä5ning Pekare/VK 20
Ini.eringslista struct Course char* name; float credits; ; int numberofparticipants; struct Course kurs1 = "MOP", 7.5f, 110; struct Course kurs2 = "MOP", 7.5f; ini.eringslista En struct kan ini.eras med en ini.eringslista. Ini.eringen sker i samma ordning som deklara.onerna, men alla medlemmar måste inte ini.eras. Fortsä5ning Pekare/VK 21
Pekare.ll struct #include <stdio.h> char* kursnamn = Maskinorienterad Programmering"; struct Course char* name; float credits; int numberofparticipants; ; int main() struct Course *pmop; pmop = (struct Course*)malloc(sizeof(struct Course)); I Java: public class Course String name; float credits; int numberofpar.cipants; Course mop = new Course(); mop.name = mop.credits = 7.5; (*pmop).name = kursnamn; pmop->name = kursnamn; pmop->credits = 7.5f; pmop->numberofparticipants = 110; Access.ll medlemmar via -> operatorn free(pmop); return 0; Fortsä5ning Pekare/VK 22
Absolutadressering 0x40011000 // ett hexadecimalt tal (unsigned char*) 0x40011000 // en unsigned char pekare som pekar på adress 0x40011004 *((unsigned char*) 0x40011000) // dereferens av pekaren // läser från 0x40011000 unsigned char value = *((unsigned char*) 0x40011000); // skriver till 0x40011004 *((unsigned char*) 0x40011004) = value; Men vi måste lägga.ll vola.le om vi har på op.meringsflaggor...! Fortsä5ning Pekare/VK 23
Vola.le qualifier char * inport = (char*) 0x40011000; void foo() while(*inport!= 0) //... En kompilator som op.merar kanske bara läser en gång (eller inte alls om vi aldrig skriver.ll adressen från programmet). Fortsä5ning Pekare/VK 24
Vola.le qualifier volatile char * inport = (char*) 0x40011000; void foo() while(*inport!= 0) //... volatile hindrar vissa op.meringar (vilket är bra och här nödvändigt!), ty anger a5 kompilatorn måste anta a5 innehållet på adressen kan ändras u.från. Vårt.digare exempel, nu korrekt med vola.le: unsigned char value = *((volatile unsigned char*) 0x40011000); // läser från 0x40011004 *((volatile unsigned char*) 0x40011004) = value; // skriver till 0x40011004 Fortsä5ning Pekare/VK 25
Portadressering med structs Istället för: #define portmoder ((volatile unsigned int *) (PORT_DISPLAY_BASE)) #define portotyper ((volatile unsigned short *)(PORT_DISPLAY_BASE+0x4)) #define portospeedr ((volatile unsigned int *) (PORT_DISPLAY_BASE+0x8)) #define portpupdr ((volatile unsigned int *) (PORT_DISPLAY_BASE+0xC)) #define portidrlow ((volatile unsigned char *) (PORT_DISPLAY_BASE+0x10)) #define portidrhigh ((volatile unsigned char *) (PORT_DISPLAY_BASE+0x11)) #define portodrlow ((volatile unsigned char *) (PORT_DISPLAY_BASE+0x14)) #define portodrhigh ((volatile unsigned char *) (PORT_DISPLAY_BASE+0x14+1)) Så kan vi utny5ja structs genom a5 skriva: typedef struct uint32_t moder; uint16_t otyper; // +0x4 uint16_t otreserved; uint32_t ospeedr; // +0x8 uint32_t pupdr; // +0xc uint8_t idrlow; // +0x10 uint8_t idrhigh; // +0x11 uint16_t idrreserved; uint8_t odrlow; // +0x14 uint8_t odrhigh; // +0x15 uint16_t odrreserved; GPIO; typedef volatile GPIO* gpioptr; #define GPIO_D (*((gpioptr) 0x40020c00)) #define GPIO_E (*((gpioptr) 0x40021000)) Exempel: GPIO_E.moder = 0x55555555; GPIO_E.otyper = 0x00000000; GPIO_E.ospeedr = 0x55555555; GPIO_E.pupdr &= 0x55550000; Fortsä5ning Pekare/VK 26
Portadressering individuella bytes Nyss definierade vi idrlow och idrhigh som bytes och idrreserved som 16-bits. Men vi skulle istället kunna ha definierat alla dessa tre som bara uint32_t idr; dvs 4 bytes och sedan addressera individuella bytes uint8_t x = *((uint8_t*)&(gpio_e.idr) + 0); // idrlow uint8_t y = *((uint8_t*)&(gpio_e.idr) + 1); // idrhigh uint16_t z = *((uint16_t*)&(gpio_e.idr) + 1); // idrreserved typedef struct uint32_t moder; uint16_t otyper; // +0x4 uint16_t otreserved; uint32_t ospeedr; // +0x8 uint32_t pupdr; // +0xc uint8_t idrlow; // +0x10 uint8_t idrhigh; // +0x11 uint16_t idrreserved; uint8_t odrlow; // +0x14 uint8_t odrhigh; // +0x15 uint16_t odrreserved; GPIO; typedef volatile GPIO* gpioptr; #define GPIO_E (*((gpioptr) 0x40021000)) typedef struct _gpio uint32_t moder; uint32_t otyper; // +0x4 uint32_t ospeedr; // +0x8 uint32_t pupdr; // +0xc uint32_t idr; // +0x10 uint32_t odr; // +0x14 GPIO; typedef volatile GPIO* gpioptr; #define GPIO_E (*((gpioptr) 0x40021000)) Fortsä5ning Pekare/VK 27
Portadressering med structs typedef struct tag_usart vola.le unsigned short sr; vola.le unsigned short Unused0; vola.le unsigned short dr; vola.le unsigned short Unused1; vola.le unsigned short brr; vola.le unsigned short Unused2; vola.le unsigned short cr1; vola.le unsigned short Unused3; vola.le unsigned short cr2; vola.le unsigned short Unused4; vola.le unsigned short cr3; vola.le unsigned short Unused5; vola.le unsigned short gtpr; USART; #define USART1 ((USART *) 0x40011000) Exempel: *USART1.dr = (unsigned short) 'a'; resp: while (( *USART.sr & 0x80)==0); Eller med pilnota.on: USART1->dr = (unsigned short) 'a ; resp: while (( USART->sr & 0x80)==0); Fortsä5ning Pekare/VK 28
Funk.onspekare #include <stdio.h> int square(int x) return x*x; int main() int (*fp)(int); En funk.onspekare fp = square; printf("fp(5)=%i \n", fp(5)); return 0; fp(5)=25 Fortsä5ning Pekare/VK 29
Funk.onspekare int (*fp)(int); Funk.onspekarens typ bestäms av: Returtyp. Antal argument och deras typer. Funk.onspekarens värde är en adress. Fortsä5ning Pekare/VK 30
Likheter assembler C Både funk.oner och globala variabler har adresser i minnet, men vi använder symboler..align 2 delay: movs r3, #255 loop_delay: subs r3, r3, #1 ands r3, r3, #255 bne loop_delay bx lr.align 4 var1:.space 4 int var1; void delay() unsigned char tmp = 255; do tmp--; while(tmp); Fortsä5ning Pekare/VK 31
Structs med funktionspekare påminner om klassmetoder I C: typedef struct tcourse void (*addstudent)(struct tcourse* crs, char* name); Course; void funcaddstudent(course* crs, char* name) // some C function Like a class method! - but needs 4 extra bytes (for the func.on pointer) in the struct. Java/C++ store all the class methods in a separate ghost struct. void main() Course mop; mop.addstudents = funcaddstudent; // set the function pointer to our desired function mop.addstudent(&mop, Per ); // call addstudent() like a class method Fortsä5ning Pekare/VK 32
Structs med funktionspekare påminner om klassmetoder I C: typedef struct char* name; float credits; int numberofparticipants; char* students[100]; void (*addstudent)(course* crs, char* name); Course; void funcaddstudent(course* crs, char* name) crs->students[crs->numberofpatricipants++] = name; void main() struct Course mop; I Java: public class Course String name; float credits; int numberofpar.cipants; String[] students; void addstudent(string name); Course mop = new Course(); mop.name = mop.credits = 7.5; mop.addstudent( Per ); mop.name = "Maskinorienterad Programmering"; mop.credits = 7.5f; mop.numberofparticipants = 0; mop.addstudents = funcaddstudent; // set the function pointer to our desired function while( ) mop.addstudent(&mop,...); // run the rest of the program Fortsä5ning Pekare/VK 33
Structs med funktionspekare exempel uppg. 39-40 arbetsboken typedef struct tobj PGEOMETRY geo; int dirx,diry; int posx,posy; void (* draw ) (struct tobj *); void (* move ) (struct tobj *); void (* set_speed ) (struct tobj *, int, int); OBJECT, *POBJECT; // store all objects in global array OBJECT* obj[] = &ball, &player; // In some function: // - move and draw all objects for(int i=0; i<sizeof(objs); i++) obj[i]->move(obj[i]); obj[i]->draw(obj[i]); ; static OBJECT ball = &ball_geometry, // geometri för en boll 0,0, // move direction (x,y) 1,1, // position (x,y) draw_object, // draw method move_object, // move method set_object_speed // set-speed method ; static OBJECT player = &player_geo, // geometri för en boll 0,0, // move direction (x,y) 10,10, // position (x,y) draw_player, // draw method move_player, // move method set_player_speed // set-speed method ; 34