Home

AVR interfaces: SPI, I2C, and UART

image

Contents

1. void TwoDigits byte data helper function for WriteDate amp WriteTime input is two digits in BCD format output is two ASCII numeric characters byte temp data gt gt 4 get upper digit Generic PutChar tempt 0 send it data amp Ox0F get lower digit Generic PutChar datat 0 send it void WriteDate outputs the current date in mm dd yy format byte months days years DS1307 _GetDate amp months amp days amp years TwoDigits months mm Generic _PutChar TwoDigits days dad Generic PutChar TwoDigits years yy Generic PutChar void WriteTime outputs the current time in hh mm ss format byte hours minutes seconds DS1307 GetTime amp hours minutes amp seconds TwoDigits hours hh Generic PutChar TwoDigits minutes mm Generic PutChar TwoDigits seconds ff ss Generic PutChar void UART_SendInt int data sends the integer value to output console ener stig save enough space for result itoa data st 10 convert to ascii string base 10 UART_SendString st display it on LCD void UART_SendHex int data sends the hexadecimal value to output console char st save enough space for result itoa data st 16 convert to ascii string base 16 UART_SendString st display it on LCD void ANSI GotoXY int x int y send ANSI escape
2. while TW READY wait TWDR addr load device s bus address TWCR TW_SEND and send it while TW READY wait return TW_STATUS 0x18 return 1 if found 0 otherwise byte I2C_FindDevice byte start returns with address of first device found 0 not found for byte addr start addr lt 0OxFF addrt search all 256 addresses if 12C_Detect addr I2C detected return addr leave as soon as one is found return 0 none detected so return 0 void I2C_ Start byte slaveAddr I2C_ Detect slaveAddr byte I12C Send byte data sends a data byte to slave TWDR data load data to be sent TWCR TW_SEND and send it while TW READY wait return TW_STATUS 0x28 byte I2C_ReadACK reads a data byte from slave TWCR TW ACK ack will read more data while TW READY wait return TWDR ceturn TW_STATUS 0x28 byte I2C ReadNACK TWCR TW_NACK while TW READY return TWDR ceturn TW_STATUS 0x28 void I2C_Write byte busAddr byte data I2C_Start busAddr I2C_Send data I2C_Stop void I2C WriteRegister byte busAddr byte I2C_Start busAddr i I2C_Send deviceRegister I2C_Send data I2C_Stop reads a data byte from slave nack not reading more data wait send bus address then send the data byte deviceRegister byte data send bus address first byt
3. as bus capacitance As a practical matter most 12C devices run at 100 kHz The DS1307 runs at 100 kHz Again keep in mind there are already libraries available for using 12C with your AVR or arduino You do not need to do this yourself A search for I2C master library will turn up a few alternatives Keep reading if you d like roll your own There are two special registers on the ATmega which control the SCL frequency TWSR and TWBR TWSR is the TWI status register and contains prescalar bits used to divide the CPU clock frequency We do not need a prescalar so we can ignore these bits The TWBR is the bit rate register The SCL frequency is a function of the CPU frequency and this register according to the following formula F_SCL in MHz F_CPU 16 2 TWBR Kinda complicated isn t it To determine the value of TWBR we can rewrite it like this TWBR F_CPU F_SCL 16 2 My CPU has a 16 MHz clock and want to run the interface in standard 100 kHz mode So the value of TWBR must be 16 0 1 16 2 160 16 2 72 define F_CPU 16000000L CPU clock speed 16 MHz define F_SCL 10800000L I2C clock speed 100 kHz void I2C_Init at 16 MHz the SCL frequency will be 16 16 2 TWBR assuming prescalar of so for 100KHz SCL TWBR F_CPU F_SCL 16 2 16 0 1 16 2 144 2 72 TWSR set prescalar to zero TWBR F_CPU F_SCL 16 2 set SCL frequency in TWI bit register Here is the protocol for se
4. bits no parity 1 stop bit The first control register UBRRO controls the data transmission rate The value is determined from the desired baud rate and CPU frequency For example a baud rate of 9600 bps on my 16 MHz controller requires a register value of 16000000 9600 16 1 130 Setting bits 4 and 3 in the second control register UCSROB enables the special Rx amp Tx data lines The third control register UCSROC sets the data frame format For 8N1 the most common data frame format the register value should be set to 0x06 Check out the AVRmega328 datasheet for information on all of the available options Once initialized the controller handles all of the implementation details Reading amp writing byte sized data from to the UART data register UDRO looks like this define RX READY UCSROA amp 0x80 check bit7 of UCSRAO define TX READY UCSROA amp 0x20 check bit5 of UCSRAO void UART_ Write byte data while TX_READY wait until ready to send UDRO data OK send it now byte UART Read while RX_READY wait until byte rec d return UDRO OK return it In both routines the first line waits until the UART is ready to send receive The second line writes reads the data register That s pretty simple isn t it 6 TESTING THE UART INTERFACE The UART uses two data lines so try a loopback test like the one for SPI Tie the Tx PD1 TxD and Rx PDO RxD lines together and r
5. by Adafruit n BLAI Oco o GINA E Docs nt A quer Next connect your DS1307 module Run the SDA line to A4 PC4 Run the SCL line to A5 PC5 And power the module with 5V and GND Your module must include pullup resistors on the SDA and SCL lines all sesesas EErEE 5 ceecee DC Boarduino T EErEE E O f v3 gt A vecere HE HIFA E Eo 4 pe e DK R f ei TAA S git Bt ie P T era oi Hi g DS1307 RTC sal lt ez 8 ee kz k a FTDI Friend ae CEE E eae e xzgsepwepwepuwpeemeeveeree e EE E Sarason You should have two lines running from the clock module to the micro and two lines from the micro your USB adapter Once everything is connected verify that your computer recognizes the FTDI board Connect a USB cable between your computer and the adapter and then check the computer s device manager gt ports You should see a USB serial port listed such as COMO If not follow the device manufacturer s recommendation for installing the appropriate driver Next you need a console application Windows used to have a preinstalled application called Hypertext but it is no longer available on all computers recommend one called PuTTY which available at putty org and elsewhere In putty exe select connection type serial and enter the name of the communication port such as COM9 that you got fro
6. device select line usually select is active low 6 Start the SPI with SPI Init 7 Transfer bytes between micro and device with SPI _Xfer SPI Status Control Register SPCR b7 b6 pI b4 bs b2 j opi bo f SPCR SPIE SPE DORD MSTR CPOL CPHA SPR1 SPRO 0 ul 0 Et ys O 0 0 i SPIE enable SPI interrupt les SPE enable SPI DORD 0 MSB first 1 LSB first MSTR O slave l master CPOL 0 clock starts low 1 clock starts high CPHA O read on rising edge 1 read on falling edge SPRz 00 os e 4 Ol ose 16 10 ose 64 1ll 08 c 128 SPCR 0x50 SPI enabled as Master mode 0 at 16 4 4 MHz void SPI_Init SPCR 0x50 SPI enabled as Master ModeO at 4 MHz SetBit SPSR SPI2X double the SPI rate 4 gt 8 MHz void SPI Close SPCR 0x00 clear SPI enable bit byte SPI Xfer byte data SPDR data initiate transfer while SPSR amp 0x80 wait for transfer to complete if ae if as return SPDR How Te I2C TWI ROUTINES to use the IZG Set the data transmission speed in the F_SCL define Common speeds are 100 kHz 100000L and 400 kHz 400000L The microcontroller is Master and the external device is Slave 2 Connect the data line SDA PC4 to the external device SDA line 3 Connect the clock SCL PC5 to the external device SCL line 4 Attach 3 3K pullup resistors from SDA to Vcc and SCL to Vcc 5 Start th
7. net eens eo ene ene Seen pees ae ee eee eee ees eae ene eee ene sane tied MISC ROUTINES void msDelay int delay put into a routine to remove code inlining for int i 0 i lt delay it at cost of timing accuracy _delay ms 1 void FlashLED byte count flash the on board LED at 3 Hz SetBit DDRB LED make sure PB5 is an output for count count SetBit PORTB LED turn LED on msDelay 100 wait ClearBit PORTB LED turn LED off msDelay 200 wait long IntToBCD int i converts an integer into its Hex BCD equivalent Ex decimal 32 gt 0x32 lon byt whi g ans 0 e digit shiftvalue 0 le i gt 0 digit i 10 get least significant decimal digit ans digit lt lt shiftvalue add it in proper position i 10 remove least significant digit shiftvalue 4 bump up digit position in answer return ans fo SSSSe 2 SPI ROUTINES if How to use the SPI rA 1 The data rate is set in SPI_Init by setting bits in the SPCR below By default the rate is FCPU 2 8 MHz for a 16 MHz board ie The microcontroller is Master and the external device is Slave 2 Connect the transmit line MOSI D11 PB3 to the external device MOSI line 3 Connect the receive line MISO D12 PB4 to the external device MISO line 4 Connect the serial clock SCK D13 PB5 to the external device SCK line 5 Ground the external
8. K send it now byte UART Read while RX_READY wait until byte rec d return UDRO OK return it byte UART KeyPressed returns 0x80 if input available 0 otherwise return RX READY void UART_SendString char st send a string to the UART for st stt for each non nul character UART_ Write st send it to uart char UART GetString char st get a string of characters 80 max from the UART string is returned when lt enter gt key is pressed ghar C byte count 0 while count lt 80 amp amp c UART Read r UART_Write c echo char back to console st countt c add char to string st count 0 add NULL termination return st f SSeseSeSSosssasosse Sea SSeS SS Sa SSS SS SaaS Sa SSS ae SSS SSS SSS 5 Se 5 DS1307 RTC ROUTINES define DS1307 0xD0 12C bus address of DS1307 RTC define SECONDS REGISTER 0x00 define MINUTES REGISTER 0x01 define HOURS REGISTER 0x02 define DAYOFWK_REGISTER 0x03 define DAYS REGISTER 0x04 define MONTHS REGISTER 0x05 define YEARS REGISTER 0x06 define CONTROL REGISTER 0x07 define RAM_BEGIN 0x08 define RAM_END 0x3F void DS1307_GetTime byte hours byte minutes byte seconds returns hours minutes and seconds in BCD format hours I2C_ReadRegister DS1307 HOURS_REGISTER minutes 2C_ReadRegister DS1307 MINUTES REGISTER seconds I2C_ReadRegister DS1307 SECONDS REGISTER i
9. L CPHA SPR1 SPRO 0 1 0 1 0 0 0 0 The first bit on the left SPIE enables the SPI interrupt and is not needed for this application The SPE bit enables SPI DORD determines the data direction when 0 the most significant bit is sent amp received first MSTR determines if the micro acts as a master 1 or slave 0 device CPOL and CPHA together determine the transfer mode Our TFT display works well with Mode 0 in which both bits are zero Finally SPR1 and SPRO determine the transfer speed as a fraction of the microcontroller s oscillator When both are 0 the SPI transfer speed is osc 4 which on my 16 MHz micro is 16 4 4 MHz When both bits are 1 the transfer speed is osc 256 62 5 kHz Using an SPCR value of 0x50 SPI is enabled as Master in Mode 0 at 4 MHz The code to open SPI communication can be as simple as the following void SPI _Init SPCR 0x50 SPI enabled as Master ModeO at 4 MHz To close SPI just set the SPE bit to 0 This will stop SPI and return the four dedicated SPI lines MOSI MISO SCLK SS to the general purpose I O functions void SPI Close SPCR 0x00 clear SPI enable bit Only one more routine is needed the SPI transfer routine SPI is a bidirectional protocol with two separate data lines The data is transmitted over MOSI and received over MISO at the same time Even if we only want to send we are always going to receive And vice versa If y
10. RTB amp _BV PORTBS turn LED off _delay ms 250 wait Now disconnect the microcontrollers MOSI digital 11 PB3 from the TFT display and connect it to the microcontroller s MISO line digital 12 PB4 Run the following code void SPI_LoopbackTest SPI Init start communication to TFT char i SPI_Xfer 5 MISO to MOSI gt returns 5 MISO to 5V gt returns 255 MISO to Gnd gt returns 0 SPI_Close return portB lines to general use FlashLED i 1 flash returned value 1 What happens If all goes well the LED will flash 6 times The value 5 is sent out the MOSI line comes back in on the MISO line and is returned from the SPI xfer routine You may wonder if Xfer worked at all Maybe nothing was transferred the value 5 could have stayed in the transfer register untouched How can we know for sure For the doubters out there like me take your wire on the MISO line and put to ground logic 0 Now all bits shifted in will be 0 and the value returned should be 0x00000000 0 If you run the program now the LED should flash only once To further convince you connect MISO to 5V Now all bits shifted in will be one and the value returned will always be 0x11111111 255 The LED should not flash at all since 255 1 256 0 for byte sized variables have posted an SPI project that drives a TFT display at http w8bh net avr AvrT FT pdf 4 THE I C INTERFACE Atmel ca
11. Serial Interfaces SPI 12C UART Demystified Bruce E Hall W8BH sonas vaasi Objective learn how to use SPI l2C and UART on your AVR microcontroller 1 INTRODUCTION It took me a long time to get here I ve used various flavors of AVR microcontrollers writing to them in assembly C and Arduino wiring processing For some reason always avoided using the built in serial communication hardware Often used someone else s serial library Sometimes emulated the protocol using GPIO pins But eventually realized that using the built in interfaces isn t difficult after all Here is my collection of quick n dirty serial interface routines This is all hobby grade material no fancy objects no long list of initialization options or interrupt driven code with ring buffers But follow along and you ll be able to use the serial hardware with minimal fuss and minimal code At the end I ll use the UART and I2C interfaces in a small RTC project 2 SERIAL PERIPHERAL INTERFACE SPI At its core the SPI algorithm is very straightforward e Puta data bit on the serial data line e Pulse the clock line e Repeat for all the bits you want to send usually 8 bits at a time You must set the microcontroller s SPI control register SPCR to enable SPI communication This is an eight bit register that contains the following bits SPCR 0x50 bit 7 bit 6 bit 5 bit 4 bit 3 bit 2 bit 1 bit 0 SPIE SPE DORD MSTR CPO
12. code to console that move cursor to x y UART_SendString 033 UART_SendInt x UART_Write UART_SendInt y UART_Write H F r void ANSI_ClearScreen sends ANSI escape codes to console that clear the screen see http ascii table com ansi escape sequences php UART_SendString 033 2J3 033 H clear amp goto top left void UART_LoopbackTest UART Write 5 send a 5 out the Tx line byte b UART Read list on Rx line FlashLED b indicate value returned int PromptInt char prompt prompts user for integer input returns input value char st 80 temp buffer for user input UART_SendString prompt display the prompt on console UART_GetString st get user s input return atoi st convert to integer amp return it int PromptHex char prompt prompts user for hexadecimal input returns input value char st 80 temp buffer for user input UART_SendString prompt display the prompt on console UART_GetString st get user s input return strtol st NULL 16 convert to integer amp return it void Console SetTimeDate interactive way to set DS1307 date amp time via TTY console int mon day year hour min mon PromptInt r nEnter the month 1 12 or 0 to skip if mon return day PromptInt r nEnter the day 1 31 year PromptInt r nEnter the 2 digit year hour PromptIn
13. e SPI with I2C Init 6 Reading amp Writing data to is often device specific ii use 12C Send to send a raw byte over the bus ff use 12C Write to send a byte to a specific bus address use I2C WriteRegister to send a byte to a specific device register la use I2C ReadAck to read a byte from slave with an acknowledgment use I2C_ ReadNACK to read a byte from slave with no acknowledgment if use I2C ReadRegister to read a byte from a specific device register define F_SCL 100000L I2C clock speed 100 KHz define READ T define TW_START OxA4 send start condition TWINT TWSTA TWEN define TW_STOP 0x94 send stop condition TWINT TWSTO TWEN define TW_ACK OxC4 return ACK to slave define TW_NACK 0x84 don t return ACK to slave define TW_SEND 0x84 send data TWINT TWEN define TW_READY TWCR amp 0x80 ready when TWINT returns to logic 1 define TW_STATUS TWSR amp OxF8 returns value of status register define I2C_Stop TWCR TW_STOP inline macro for stop condition void I2C_Init at 16 MHz the SCL frequency will be 16 16 2 TWBR assuming prescalar of 0 so for 100KHz SCL TWBR F_CPU F_SCL 16 2 16 0 1 16 2 144 2 72 TWSR 0 set prescalar to zero TWBR F_CPU F_SCL 16 2 set SCL frequency in TWI bit register byte I2C_ Detect byte addr look for device at specified address return 1 found O not found TWCR TW_START send start condition
14. e device register address second byte data for device register byte I2C_ReadRegister byte busAddr byte deviceRegister byte data 0 I2C_Start busAddr I2C_Send deviceRegister I2C_Start busAddr READ i data I2C ReadNACK I2C_Stop if return data 0 Fee oa ee eee ams oes USART ROUTINES How to use the USART ta 1 Set the serial transmission speed rates are 300 1200 2400 4800 hl The mode is set at 8 data bits 1 2 Connect the transmit line Tx PD1 3 Connect the receive line Rx PDO 4 Start the UART with UART Init ti Be define BAUDRATE 9600 define RX READY UCSROA amp 0x80 Li define TX_READY UCSROA amp 0x20 void UART Init UBRRO F_CPU BAUDRATE 16L 1 fy UCSROB 0x18 UCSROC 0x06 void UART Close UCSROB 0x00 void UART_ Write byte data while TX READY send device address set register pointer restart as a read operation read the register data stop in the BAUDRATE define Common baud 9600 14400 19200 28800 57600 stop bit no parity most common to the external device Rx line to the external device Tx line Send bytes with UART_ Write Receive bytes with UART_Read check bit7 of UCSRAO check bit5 of UCSRAO set speed according to BAUDRATE define enable UART set Rx Tx enable bits 8 data bits no parity set mode 1 stop bit disable Rx Tx wait until ready to send UDRO data O
15. e value for TW_STOP Again this value sets the TW enable TW interrupt and TW stop bits Go ahead use 1 lt lt TWINT 1 lt lt TWEN 1 lt lt TWSTO if you prefer We do not have to wait or check for status codes so it is just a one line command Instead of writing a routine made a macro instead define TW_STOP 0x94 send stop condition TWINT TWSTO TWEN define I2C_Stop TWCR TW_STOP inline macro for stop condition Just a quick note on the status codes I ve written my routines to check the status but ignore the results In my simple setup this works OK You may want to check each code and show error messages when appropriate Reading data is little trickier we have to write to the device first to set its internal address pointer and then read to get the data at that address Here is the protocol for receiving data from the slave e Master generates Start Condition status code 0x08 is returned e Master sends slave bus address 0xd0 DS1307 returns ACK status code 0x18 e Master sends address pointer slave device returns ACK status code 0x28 e Master generates another Start Condition restart status code 0x10 returned e Master sends slave bus address read bit 0xd1 slave returns ACK status code 0x40 e Master requests data byte with NACK slave returns byte status code 0x58 e Master sends Stop condition no status code returned The only new code required for reading is the read operation in the ne
16. f hours amp 0x40 12hr mode hours amp 0x1F use bottom 5 bits pm bit temp amp 0x20 else hours amp 0x3F 24hr mode use bottom 6 bits void DS1307 GetDate byte months byte days byte years returns months days and years in BCD format months I2C ReadRegister DS1307 MONTHS REGISTER days I2C_ReadRegister DS1307 DAYS REGISTER years I12C_ ReadRegister DS1307 YEARS REGISTER void DS1307 Now byte months byte days byte years byte hours byte minutes byte seconds DS1307 GetDate months days years DS1307 GetTime hours minutes seconds void DS1307 SetTimeDate byte mon byte day byte year byte hour byte min note hours are 0 23 years are 2 digit 2014 is 14 byte adj 0 if hour gt 11 hour 12 adj 0x40 set 12 hr mode 2C_WriteRegister DS1307 MONTHS REGISTER IntToBCD mon 2C_WriteRegister DS1307 DAYS REGISTER IntToBCD day 2C_WriteRegister DS1307 YEARS REGISTER IntToBCD year 2C WriteRegister DS1307 HOURS REGISTER IntToBCD hour ad 2C WriteRegister DS1307 MINUTES REGISTER IntTOBCD min 2C_WriteRegister DS1307 SECONDS REGISTER 0x00 seconds at 00 nanan nnn nnn nnn nnn nnn nnn nnn nnn nn nnn nnn nnn nn nnn nnn nnn nena APPLICATION ROUTINES void Generic PutChar char ch called when its time to output a character output device can be UART LCD whatever UART Write ch
17. le TWI module You will see many people write it like this TWCR 1 lt lt TWINT 1 lt lt TWSTA 1 lt lt TWEN Most think that this self documenting style of coding is preferable so please use it if you like For me start is simply code 0xA4 The next thing to do is send the bus address of the slave we are communicating with For example the DS1307 real time clock has a bus address of Oxd0 Here is our code to do that define DS1307 xDO I2C bus address of DS1307 RTC define TW_SEND 0x84 send data TWINT TWEN byte I2C_SendAddr addr send bus address of slave TWDR addr load device s bus address TWCR TW_SEND and send it while TW_READY wait return TW_STATUS 0x18 return 1 if found otherwise Put the address of the slave device into TWDR put the send command in TWCR and wait The next operation sending a data byte looks almost exactly the same Notice that the returned status code will be different however byte I2C_Write byte data sends a data byte to slave TWDR data load data to be sent TWCR TW_SEND and send it while TW_READY wait return TW_STATUS 0x28 return 1 if found otherwise For the DS1307 we will do this Write operation twice once to set the address pointer on the RTC and again to supply the data for that address The last step is the send the Stop condition Here we just set the command register to 0x94 th
18. lls their version of 12C the two wire interface or TWI It is a serial data protocol which uses two data lines for communication a data line SDA and a clock SCL Devices on the I2C bus can either be masters or slaves Masters initiate data transfers and slaves react only to master requests In this article the AVRmega328 is the master and the RTC is always the slave Slaves are specified by a 7 bit address plus a read write bit The device address for the DS1307 is fixed at Oxd0 e gt The interface circuit is open collector which means m r that the data lines are passively kept high by resistors to N device device device oH J aaa Vcc Any device on the bus can actively pull a data line low Up to 128 devices can be put on the same data bus There are plenty of good articles on TWI I2C programming for AVR microcontrollers Check out the following for a good start 1 Non GNU org http www nongnu org avr libc user manual group twi _demo html 2 AVR beginners http www avrbeginners net architecture twi twi html 3 ATMEL AVR315 http www atmel com Images doc2564 pdf Compared with SPI using 12C is a bit more involved The first job is to set the frequency of the serial data clock Typically the clock frequency is 10 slow mode 100 standard mode or 400 fast mode kHz The maximum clock rate is determined by the slowest device on the bus as well
19. m the device manager If you are doing this for the very first time you can easily verify that the USB adapter and console app are configured correctly temporarily disconnect both data lines between the micro and the adapter Now do a loopback test by connecting the adapter s Tx and Rx lines together Anything you type in the console application will be sent out the Tx line back into Rx and be displayed on the console screen If you have more than one application running on your computer make sure the console app is on top and has focus Once the console app and USB adapter are working let s add our microcontroller and extend the loopback test void Typewriter for char ch 0 ch wait for stop char i ch UART Read get byte from keyboard UART_Write ch send it to output if ch r f LE it is a lt return gt UART_Write n add a lt newline gt This code will read a byte from the UART and echo it back to the console There is a check for the return character since lt return gt doesn t bump the cursor to the next line on my console Now instead of writing to the LCD via LCD_Char we send the data to the computer screen via UART_Write The source code below shows the slightly modified routines In addition we can prompt the user for updated time information and get the information via keyboard input Many console applications do terminal emulation and allow you to con
20. nding data from master to slave MT master transmit mode e Master generates Start Condition status code 0x08 is returned e Master sends slave address 0xd0 slave device returns ACK status code 0x18 e Master sends one or more data bytes slave device returns ACK status code 0x28 e Master generates Stop Condition no status code returned After each operation the ready bit in TWCR will go to logic 0 and return to logic 1 when the operation is completed Byte sized data is sent received via the special TWDR register The start stop and data transfer conditions are specified by the TWCR control register And the status codes are put in the TWSR register Let s look at the code and compare it to the protocol Here is how to generate a start condition define TW_START OxA4 send start condition TWINT TWSTA TWEN define TW_READY TWCR amp 0x80 ready when TWINT returns to logic 1 define TW_STATUS TWSR amp xF8 returns value of status register byte I2C_Start generate a TW start condition TWCR TW_START send start condition while TW_READY wait return TW_STATUS 0x 8 return 1 if found otherwise To generate a start load TWCR with 0xA4 and wait That s all there is to it Why 0xA4 OxA4 is binary 10100100 The three 1 values correspond to the TWINT TWSTA and TWEN bits of the control register These bits enable the TWI interrupt the start condition and the who
21. o run in synchronous mode so it is often called a USART A good article about the hardware is at avrbeginners net And a good programming reference is Dean Camera s UART article at fourwalledcubicle com Typical speed 1 20 MHz 100 400 kHz 9 56 kHz Typical use High speed hardware Multiple devices ona Keyboard character common bus LCD Monitor As opposed to SPI and I2C which are often used for binary data exchange between hardware devices UART is often used for transmission of slower ASCII data For example you might use the UART for keyboard input or monitor character LCD output Speedy SPI transfers data to dedicated hardware devices at MHz speeds while UART transfers are a thousand times slower UART Frame Each data frame consists of a Start bit a variable number of data bits an optional parity bit and 1 or 2 stop bits The most common configuration is 1 start bit 8 data bits no parity bit and 1 stop bit 8N1 Message Bits 1 character Start In asynchronous mode there is no clock line data is transmitted on the transmit line Tx and received on the receive line Rx The UART is initialized by configuring control registers that determine the baud rate parity number of stop bits define BAUDRATE 9600 void UART Init UBRRO F_CPU BAUDRATE 16L 1 set speed according to BAUDRATE define UCSROB 0x18 enable UART set Rx Tx enable bits UCSROC 0x06 set mode 8 data
22. ou aren t expecting any received data just ignore what is returned to you The data transfer register is SPDR Load this register with a value and the data transfer will start automatically A bit in SPSR the status register will tell us when the transfer is complete As the data bits are serially shifted out of the transfer register the received bits are shifted in When the transfer completes SPDR will hold the received data byte SPI Xfer byte data you can use uint8 t for byte SPDR data initiate transfer while SPSR amp 0x80 wait for transfer to complete return SPDR 3 TESTING THE SPI INTERFACE The three routines above are all we need for SPI Let s make sure they work by doing a serial loop back test In this test the output data on MOSI is looped back as the input on MISO Whatever value we put into the data register should come right back in Without a working display we need a way to verify the data You might want to use your fancy debugger or send the value to a monitor via UART but here is something even simpler flash the LED on your controller board Most AVR boards have a connected LED On many AVR boards including the Arduino the status LED is on PB5 Here is a routine to flash it void FlashLED byte count flash the on board LED at 2 Hz DDRB _BV DDB5 Set PBS as output for count gt 0 count PORTB _BV PORTBS turn LED on _delay ms 250 wait PO
23. t r nEnter the hours 0 23 min PromptInt r nEnter the minutes 0 59 DS1307 SetTimeDate mon day year hour min void Typewriter UART_SendString r n gt Welcome to W8BH Type to stop r n for char ch 0 ch wait for stop char Ti ch UART_Read get byte from keyboard UART_Write ch send it to output if ch r if it is a lt return gt UART Write n add a lt newline gt UART_SendString r n gt Bye r n I MAIN PROGRAM int main UART_Init I2C_Init Typewriter ANSI_ClearScreen Console SetTimeDate ANSI_ClearScreen UART_SendString Welcome to W8BH Current Time while 1 forever ANSI_GotoxyY 4 6 goto line 4 col 6 WriteDate show date time WriteTime msDelay 5000 wait 5 seconds
24. trol the cursor and display colors via escape codes See http ascii table com ansi escape sequences php for a list of these codes In the source code ANSI escape sequences are used for clearing the screen and for setting cursor position 9 SOURCE CODE Serial interfaces useful SPI I2C and UART routines Author Bruce E Hall lt bhall66 gmail com gt Website http w8bh net avr serial pdf Version 1 0 Date 12 May 2014 Target ATmega328P microcontroller Language C using AVR studio 6 Size 1994 bytes Fuse settings 8 MHz osc with 65 ms Delay SPI enable NO clock 8 if Demo will get time amp date info from from DS1307 RTC module via I2C and display time amp date on computer console via UART if e SReee eon ses gt anaes een earn eee eee pees en R E eo ees pene een eee ena R GLOBAL DEFINES define F_CPU 16000000 run CPU at 16 MHz define LED 5 Boarduino LED on PB5 define ClearBit x y x amp _BV y equivalent to cbi x y define SetBit x y x _BV y equivalent to sbi x y D a i gg a E Va INCLUDES include lt avr io h gt deal with port registers include lt util delay h gt used for _delay ms function include lt stdlib h gt used for itoa atoi PP Bee S SSeS Se SS ee ee ee TYPEDEFS typedef uint8 t byte I just like byte amp sbyte better typedef int8 t sbyte a a a a ee fz GLOBAL VARIABLES Seeet ee Sonone
25. un the following routine void UART LoopbackTest UART Write 5 send a 5 out the Tx line byte b UART Read listen on Rx line FlashLED b indicate value returned If all goes well the LED should flash 5 times 7 MAKING LIBRARIES Each of the interfaces is a great candidate for a library For example put the three SPI routines in a file called spi c Then make a header file called spi h that includes only the function declarations Do the same for UART and I2C Now you can include whichever interface you need like this include spi h 8 DS1307 RTC REVISITED In the DS1307 tutorial used a character LCD for output Let s use the UART interface to use our computer screen instead The AVR TxD and RxD lines require additional hardware to connect back to your PC In the old days all PCs had RS232 serial ports and you would use a Max232 chip to convert the 12V signals from the computer to the TTL 5V logic levels on the micro A quick internet search for Max232 module will give you several options costing around 5 To the left is one available for around 3 at NewEgg However most modern PCs have abandoned RS232 ports and use USB ports instead To connect AVR serial lines to USB use the FTDI friend adapter from Adafruit It will set you back mu no about 15 Connect TxD to the adapter input line E Rx RxD to the output line Tx and GND to ground K FTOI Friend
26. xt to last step It looks very similar to the write operation NACK is used to a request of a single or last byte of data define TW_NACK 0x84 read data with NACK last byte define READ 1 byte I2C_ReadNACK reads a data byte from slave TWCR TW_NACK nack not reading more data while TW_READY wait return TWDR Putting it all together here are sample routines for reading and writing registers on the slave device You will need to check the datasheet of the slave device you intend to use each device may have its own unique protocol for addressing its registers memory contents etc void I2C_WriteRegister byte deviceRegister byte data I2C_Start I2C_SendAddr DS13 7 send bus address I2C_Write deviceRegister first byte device register address I2C_Write data second byte data for device register I2C_Stop byte I2C_ReadRegister byte deviceRegister byte data 0 I2C_Start I2C_SendAddr DS13 7 send device bus address I2C_Write deviceRegister set register pointer I2C_Start I2C_SendAddr DS1307 READ restart as a read operation data I2C_ReadNACK read the register data I2C_Stop stop return data wrote a RTC tutorial using the 12C interface at http w8bh net avr AvrDS1307 pdf 5 THE UART INTERFACE Compared to 12C using the UART is darn easy UART stands for Universal Asynchronous Receive Transmit The hardware can als

Download Pdf Manuals

image

Related Search

Related Contents

KAC-80D取扱説明書(110205)  Manual de instrucciones 86078 (ES PT)  Apple Mac OS X Server 10.5 Leopard User's Manual  

Copyright © All rights reserved.
Failed to retrieve file