Synchronous Serial IO Send a separate clock line
















































- Slides: 48
Synchronous Serial IO • Send a separate clock line with data – SPI (serial peripheral interface) protocol – I 2 C (or I 2 C) protocol • Encode a clock with data so that clock be extracted or data has guaranteed transition density with receiver clock via Phase-Locked-Loop (PLL) – IEEE Firewire (clock encoded in data) – USB (data has guaranteed transition density) V 0. 3 1
Serial Peripheral Interface (SPI) SDI: data in SDO: data out SCK: clock © Charles River Media 2005 V 0. 3 2
CKE configuration bit allows either falling or rising edge of clock to be used, while CKP selects clock polarity. V 0. 3 © Charles River Media 2005 3
SPM bit selects whether data is sampled in middle of clock period or at end of clock period. © Charles River Media 2005 Between the CKP, CKE, SPM bits there is a lot of flexibility in how data is clocked in. Can make the SPI protocol work with just about any serial device. V 0. 3 4
© Charles River Media 2005 Multiple SPI peripherals each require a separate chip select line via parallel port line. We will concentrate on the I 2 C serial bus as it does not require use of chip selects. V 0. 3 5
I 2 C (Inter-Integrated-Circuit) Bus I 2 C is a two wire serial interface. 18 F 242 Vdd 10 K Microchip 24 LC 515 SCL A 2 Vdd A 1 10 K SDA SCL – clock line SDA – data (bidirectional) A 0 A 2 A 1 SDA V 0. 3 A 0 6
What is a bus? ? © Charles River Media 2005 V 0. 3 7
Ethernet is a example of a bus © Charles River Media 2005 V 0. 3 8
I 2 C Features • Multiple receivers do not require separate select lines as in SPI – At start of each I 2 C transaction a 7 -bit device address is sent – Each device listens – if device address matches internal address, then device responds • SDA (data line) is bidirectional, communication is half duplex • SDA, SCLK are open-drain, require external pullups – Allows multiple bus masters (will discuss this more later). V 0. 3 9
pullups are needed I 2 C Bus Addressing © Charles River Media 2005 No chip selects needed!!!!! V 0. 3 10
I 2 C Bus Transfer Multiple bytes sent in a transaction; every 8 bits has a 9 th bit that is an acknowledge. V 0. 3 11
Write (master to slave) Master initiates all transactions, read or write. Read (master from slave) V 0. 3 12
Example: I 2 C Serial EEPROM Will use the Microchip 24 LC 515 Serial EEPROM to discuss I 2 C operation. The 24 LC 515 is a 64 K x 8 memory. This would require 16 address lines, and 8 data lines if a parallel interface was used, which would exceed the number of available IO pins our PIC 18 F 242!!! Putting a serial interface on a memory device lowers the required pin count. Reduces speed since data has to be sent serially, but now possible to add significant external storage to a low pincount micro controller. V 0. 3 13
I 2 C Device Addressing Each I 2 C device has either a 7 -bit or 10 -bit device address. We will use an I 2 C EEPROM and an I 2 C DAC (Digital-to. Analog Converter, MAX 517) in lab. Both of these devices have a 7 -bit address. Upper four bits are assigned by device manufacturer and are hardcoded in the device. Lower three bits are used in different ways by manufacturer. LC 515 control byte (contains slave address): Microchip 24 LC 515 R/W = 1 SCL A 2 7654 3 2 1 0 for read, 0 1 0 B 0 A 1 A 0 R/W for write. A 1 ‘B 0’ is block select (upper/lower 32 K). A 1, A 0 SDA A 0 are chip selects, four devices on one bus. V 0. 3 14
IDLE: SCL, SDA high. START: high to low transition on SDA while SCL high. I 2 C Transmission Valid data: While clock is high, data valid and stable. V 0. 3 Data changes while clock is low. STOP: low to high transition on SDA while SCL high. 15
Acknowledgement ACK sent by slave after every 8 -bits received. Master releases line (stops driving), samples line on next clock. Slave MUST pull line low. If Master does not detect ACK, then sets error bit. If Slave does not pull line low, the pullup resistors will pull the line low. Most common cause of ACK error – incorrect device address. V 0. 3 16
Byte Write Operation • Byte Write: used to write one byte – Send Control Byte, High address byte, low address byte, data. – After data is sent, takes 5 ms for write to complete – SLOOOOOWWWWWW. . ‘ 0’ indicates write mode. V 0. 3 ‘X’ because block select bit chooses high or low 32 K. 17
Page Write Operation • Send a block of 64 bytes, then perform write – Send starting address, followed by 64 bytes – After 64 bytes sent, wait 5 ms for write to complete – Much faster than individual writes Address should be on a page boundary. For page size = 64 = 0 x 40, starting address should be a multiple of 64. V 0. 3 18
Speed Comparison • Assume a 400 Khz I 2 C bus, 2. 5 us clock period (2. 5 e-6) • Random write: – 9 bit transmission = 2. 5 us * 9 = 22. 5 us – 5 ms + 22. 5 us* 4 (control, addhi, addlo, data) =5. 09 ms – For 64 bytes = 325 ms approximately, not counting software overhead. • Page Write – 67 bytes total (control, addhi, addlo, data) – 5 ms + 67 * 22. 5 us = 6. 5 ms!!! V 0. 3 19
Checking for end-ofwrite Timing on write is guaranteed to finish after 5 ms. But can end sooner; to determine if write finished use polling method. No ACK means device is still busy with last write. V 0. 3 20
Read Operation: Current Address • An internal counter is used to keep track of last address used • A current address read uses this address, only sends the command byte – Internal counter incremented after read operation ‘ 1’ indicates read operation V 0. 3 ‘no ack’ because slave is driving data back to master. 21
Random Read Operation • Must first set the internal address counter by starting a write operation, but aborting by not sending data byte Aborted random write (address only, no data) V 0. 3 Current address read 22
Sequential Read • Like a current address read, but after Slave sends data byte, Master sends ACK instead of STOP – Slave then sends next byte – Can do this from 0 x 0000 h to 0 x 7 FFF (lower 32 K block). When 0 x 7 FFF is reached, address rolls over to 0 x 0000 – Upper block goes from 0 x 8000 to 0 x. FFFF; at 0 x. FFFF address rolls over to 0 x 8000 – Internal address counter is only 15 bits wide. V 0. 3 23
PIC 18 I 2 C Registers • Synchronous Serial Port on PIC implements I 2 C • Registers are: – SSPCON – control register - we will always set this to 0 x 28 which enables I 2 C MASTER mode. – SSPCON 1 – control register - used to initiate a START/STOP conditions, indicates if ACK has been received – SSPSTAT – status register – check this to see if byte finished transmitting, or byte has been received – SSPBUF – read/write to this register for data transfer – SSPADD – used to control clock rate V 0. 3 24
I 2 C on the PIC 18 • Will always use master mode on the PIC 18 – This means that the PIC will always initiate all I 2 C bus activity • To set I 2 C clock rate, write 8 -bit value to the SSPADD register – Clock rate = Fosc/(4 *(SSPADD+1)) • I 2 C standard defines 100 KHz and 400 KHz but in reality just about any clock rate from DC to 400 KHz works Clock Rate formula in SSPCON 1 description, page 136 of datasheet (page 138 PDF page), section 15 -4 of datasheet V 0. 3 25
Lab #8: Read/Write to Serial EEPROM • Lab #8 has you read/write to a Serial EEPROM via the I 2 C bus • The files i 2 cmsu. h, i 2 cmsu. c define interface subroutines for the I 2 C bus • This file i 2 c_memutil. c has subroutines for random read/write, block read/write for the serial eeprom • The file i 2 cmemtst. c tests uses the subroutines to read/write data to the serial EEPROM. V 0. 3 26
i 2 cmsu. c Subroutines • i 2 c_idle() – wait for idle condition on I 2 C bus • i 2 c_Start() – send a START and wait for START end • i 2 c_Stop() – send a STOP and wait for STOP end • i 2 c_do. Ack() – do an ACK cycle • i 2 c_do. Nak() – do a NACK cycle • i 2 c_Write. To(address) – do a i 2 c_Start(), then send address to I 2 C bus. • i 2 c_Put. Byte(byte) – write byte to I 2 C, wait for finish, then get an ACK • i 2 c_Get. Byte() – get a byte from I 2 C bus V 0. 3 27
Watchdog Timer Use The I 2 C subroutines assume the watchdog timer is enabled, so the statement: asm(“clrwdt”); is used in subroutines to clear the watchdog timer. It is NOT used in loops which wait for ACK bits from peripherals; we want the watchdog timer to expire if a peripheral does not repond with an ACK bit. V 0. 3 28
Random Read: memread(cmd, addr) cmd is unsigned char that has EEprom i 2 c device address i 2 c_Writeto (write_cmd) i 2 c_Put. Byte (address_hibyte) addr is unsigned char is memory address within EEprom i 2 c_Put. Byte (address_lobyte) i 2 c_Stop() Set internal address counter. i 2 c_Writeto (read_cmd) Read byte from current address i 2 c_Get. Byte () i 2 c_Stop() V 0. 3 29
memread(cmd, addr) Does a random read of EEPROM /* random read */ unsigned char mem_read(unsigned char cmd, int addr) { unsigned char hbyte, lbyte, val; if (addr & 0 x 8000) { // if MSB set , set block select bit cmd = cmd | 0 x 08; } hbyte = (addr >> 8) & 0 x 7 F; // high address byte lbyte = (addr) & 0 x. FF; // low address byte i 2 c_Write. To(cmd); // send write cmd, do this to set address counter i 2 c_Put. Byte(hbyte); // send high address byte i 2 c_Put. Byte(lbyte); // send low address byte i 2 c_Stop(); // send stop cmd = cmd | 0 x 1; // set read bit i 2 c_Write. To(cmd); // send read cmd, address set by previous cmd val = i 2 c_Get. Byte(); // read data i 2 c_Stop(); // send stop return(val); } V 0. 3 30
i 2 c_Writeto (write_cmd) Page Write i 2 c_Put. Byte (address_hibyte) set starting address. i 2 c_Put. Byte (address_lobyte) i = 0; i 2 c_Put. Byte (); i++ Send 64 bytes. i = 64? i 2 c_Stop() V 0. 3 31
Page (Block) Write /* block write */ void block_mem_write(unsigned char cmd, int addr, char *buf) unsigned char hbyte, lbyte, val; { hbyte = (addr >> 8) & 0 x 7 F; // high address byte lbyte = (addr) & 0 x. FF; // low address byte i 2 c_Write. To(cmd); // send write cmd i 2 c_Put. Byte(hbyte); // send high address byte i 2 c_Put. Byte(lbyte); // send low address byte for (k=0; k<64; k++) { Uncomment if //i 2 c_Put. Byte(buf[k]); // send data i 2 c_Fast. Put. Byte(buf[k]); // send data subroutine called } more often than 5 i 2 c_Stop(); //Delay. Ms(5); } ms. // no need to delay, will not be back here for 5 ms Fast. Put. Byte does not check for idle condition before sending data. V 0. 3 32
i 2 c_Writeto (write_cmd) Block Read i 2 c_Put. Byte (address_hibyte) set starting address. i 2 c_Put. Byte (address_lobyte) i 2 c_Stop() Send read command i 2 c_Writeto (read_cmd) i 2 c_Get. Byte (); i++ i = 64? no i 2 c_do. Ack(); yes i 2 c_Stop() V 0. 3 Use sequential read to get 64 bytes. Sequential read can read up to 32 K, block size of 64 bytes was arbitrary 33
Block Read in C /* block read */ void block_mem_read(unsigned char cmd, int addr, char *buf) { unsigned char hbyte; unsigned char lbyte; unsigned char k; if (addr & 0 x 8000) { // if MSB set , set block select bit cmd = cmd | 0 x 08; } hbyte = (addr >> 8) & 0 x 7 F; // high address byte lbyte = (addr) & 0 x. FF; // low address byte i 2 c_Write. To(cmd); // send write cmd, do this to set address counter i 2 c_Put. Byte(hbyte); // send high address byte i 2 c_Put. Byte(lbyte); // send low address byte i 2 c_Stop(); // send stop cmd = cmd | 0 x 1; // set read bit i 2 c_Write. To(cmd); for (k=0; k<64; k++){ buf[k] = i 2 c_Get. Byte(); // read data if (k== 63) i 2 c_Stop(); // last byte, so send stop else i 2 c_do. Ack(); // do ack if not at end } } V 0. 3 34
EEPROM Test: memblk. c tests serial EEPROM by doing block read/write to EEPROM. printf("Enter 'w'(write), or 'r' (read): "); pcrlf (); From main(), ask user for inchar=getch(); if (inchar == 'w') { write or read test. pcrlf (); printf("Capturing next 64 bytes for write to memory"); pcrlf (); Get 64 bytes from serial for (i=0; i<64; i++) { buf[i] = getch(); port, save in buffer. } printf("Block write to memory"); Print bytes before write to pcrlf (); EEPROM. for (i=0; i<64; i++) { printf("Write at %d, val: %x (%c) n", i, buf[i]); pcrlf (); } Write bytes to EEPROM at block_mem_write(ROM, 0, buf); address 0. printf("Mem Write complete"); pcrlf (); } elsif. . . V 0. 3 35
EEPROM Test: memblk. c printf("Enter 'w'(write), or 'r' (read): "); pcrlf (); inchar=getch(); Read 64 bytes from if (inchar == 'w') { address 0, store in buffer. // see previous slide }else if (inchar == 'r') { printf("###Reading first 64 memory locations, via a block read"); pcrlf (); block_mem_read(ROM, 0, buf); for (i=0; i<64; i++) { printf("Read %d, val: %x (%c) n", i, buf[i]); pcrlf (); } pcrlf (); Print the 64 bytes read printf("###Mem Read complete"); from EEPROM, hopefully pcrlf (); } they will match what was written! V 0. 3 36
i 2 c_idle() R/W bit, when ‘ 0’ then transmit is not in progress i 2 c_idle() { unsigned char byte 1; unsigned char byte 2; do { byte 1 = SSPSTAT & 0 x 04; byte 2 = SSPCON 2 & 0 x 1 F; }while (byte 1 | byte 2); asm(“clrwdt”); } // gte R/W bit. Check if lower 5 bits are all ‘ 0’ indicating that Start, Stop, Acknowledge sequences are all idle. V 0. 3 37
i 2 c_Start()/i 2 c_Stop() i 2 c_Start(){ i 2 c_idle(); /* initiate start, SEN=1 */ bitset(SSPCON 2, 0); /* wait until start finished */ while (bittst(SSPCON 2, 0)); asm(“clrwdt”); begin START wait for end } i 2 c_Stop() { i 2 c_idle(); /* initiate stop, PEN=1 */ bitset(SSPCON 2, 2); /* wait until stop finished */ while (bittst(SSPCON 2, 2)); asm(“clrwdt”); } V 0. 3 begin STOP wait for end 38
i 2 c_Put. Byte() i 2 c_Put. Byte(unsigned char byte) { i 2 c_idle(); i 2 c_Fast. Put. Byte deletes this call. /* write data */ SSPBUF = byte; /* wait until finished */ while(bittst(SSPSTAT, 2)); asm(“clrwdt”); /* wait for acknowledge */ while(bittst(SSPCON 2, 6)); asm(“clrwdt”); SSPBUF holds outgoing data Cleared when transmit finished. Cleared when ACK received. } If device does not respond with ACK bit, then Watchdog timer will expire. V 0. 3 39
i 2 c_Write. To(unsigned char addr) { /* first, send start */ i 2 c_Start(); SSPBUF = addr; /* write data */ /* wait until finished */ while(bittst(SSPSTAT, 2)); asm(“clrwdt”); /* wait for acknowledge */ while(bittst(SSPCON 2, 6)); asm(“clrwdt”); SSPBUF holds outgoing data Cleared when transmit finished. Cleared when ACK received. } If device does not respond with ACK bit, then Watchdog timer will expire. V 0. 3 40
i 2 c_Get. Byte() unsigned char i 2 c_Get. Byte() { unsigned char byte; i 2 c_idle(); /* initiate read event */ Enable receive bitset(SSPCON 2, 3); /* wait until finished */ while(bittst(SSPCON 2, 3)); while (!(bittst(SSPSTAT, 0))); byte = SSPBUF; return(byte); } Will be cleared when finished. Receive buffer should be full /* read data */ Get data V 0. 3 41
Differences between i 2 c_Write. To, i 2 c_Put. Byte, i 2 c_Fast. Put. Byte, i 2 c_Get. Byte() • i 2 c_Put. Byte() sends one byte, checks for idle condition first. • i 2 c_Fast. Putbyte is simply i 2 c_Put. Byte() without the idle check. – Executes faster than i 2 c_Put. Byte • i 2 c_Get. Byte() gets reads one byte • i 2 c_Write. To() initiates a start condition first, then sends one byte. – i 2 c_Write. To() used to send the first byte of a transaction – i 2 c_Put. Byte or i 2 c_Fast. Put. Byte used to send remaining bytes of transaction. V 0. 3 42
An I 2 C Transaction An I 2 C transaction is an exchange of data between the PIC and an external device over the I 2 C bus. All transactions use the calls: i 2 c_Writeto() Start Transaction i 2 c_Start() combines these Send device i 2 c_Put. Byte() two actions address Read/Write Data End Transaction sequence of i 2 c_Get. Byte, i 2 c_Put. Byte() i 2 c_Get. Byte() External PIC Device i 2 c_Stop() i 2 c_Put. Byte() External PIC Device V 0. 3 43
Lab 9: I 2 C & Serial EEPROM Goal: Capture streaming data from serial port, store to serial EEPROM Capture 64 bytes from serial port to buffer Page Write of 64 bytes Interrupt service routine stores bytes in a buffer. Problem: While writing bytes to serial EEPROM, more bytes are arriving!!! Solution: Use two buffers! Second buffer captures data while first buffer data written to EEPROM. V 0. 3 44
main() ISR Buffer B swapped when full. EEPROM When main() sees that buffer is full, tells ISR to swap buffers, then empties the full buffer. Empty buffer by writing contents to EEPROM, no longer need data after written to EEPROM. V 0. 3 Data Buffer A Interrupt Service Routine (ISR) fills data buffer, sets flag when data buffer is full. ISR is invoked for each new input character. 45
Two Buffers Char arrival triggers interrupt ISR Flowchart 0 Interrupt Service Subroutine 1 Active buffer? Save char in buff 0 no 64 bytes? Save char in buff 1 no 64 bytes? yes Write_flag = 1 exit interrupt service At least one of the 64 byte buffers MUST be in bank 1, not enough room for both in bank 0. V 0. 3 While writing data to EEPROM from one buffer, use other buffer to receive incoming data. ISR sets write_flag to indicate to main() that 64 bytes has been received, and that block_mem_write() should be called. active_buffer flag set by main() to indicate what buffer the ISR uses for byte storage. 46
Streaming Write Loop: main() Streaming Write Loop main() flowchart 0 Write_flag? Wait for interrupt service routine to fill a buffer. 1 0 Active buffer? 1 Active buffer = 0 Page write buff 1 Write_flag = 0 addr = addr + 64 V 0. 3 47
What do you have know? • Serial Peripheral Interface (SPI) – how is this different from I 2 C? • I 2 C Protocol – What is start, stop, ack conditions, purpose of each – How is data sent, received – Device addressing • Serial EEPROM – Sequential, Random Read operations – Random, Block Write operations V 0. 3 48