ECE 4510/5530 Microcontroller Applications Week 10bazuinb/ECE4510/Week10_2.pdf · ECE 4510/5530...
Transcript of ECE 4510/5530 Microcontroller Applications Week 10bazuinb/ECE4510/Week10_2.pdf · ECE 4510/5530...
ECE 4510/5530Microcontroller Applications
Week 10
Dr. Bradley J. BazuinAssociate Professor
Department of Electrical and Computer EngineeringCollege of Engineering and Applied Sciences
ECE 4510/5530
2http://www.mi.spacegrant.org/
ECE 2510 3
Lab 9 Elements
• Inter-Integrated Circuit (I2C) Interface– SCL and SDA connections– Transfers
• Start• Data• Acknowledge• Stop
• Calendar– MCP7940M-I/P Real-Time Clock/Calendar
Lab 8 Note: Serial I/O on multiple pins
ECE 4510/5530
4
Alternate Pin Connections
ECE 4510/5530
5
ECE 2510 6
The HCS12 SPI Modules• The MC9S12DP256 has three SPI modules: SPI0, SPI1, and SPI2.• By default, the SPI0 share the use of the upper 4 Port S pins:
– PS7 SS0 (can be rerouted to PM3)– PS6 SCK0 (can be rerouted to PM5)– PS5 MOSI0 (can be rerouted to PM4)– PS4 MISO0 (can be rerouted to PM2)
• By default, the SPI1 shares the use of the lower 4 Port P pins:– PP3 SS1 (can be rerouted to PH3)– PP2 SCK1 (can be rerouted to PH2)– PP1 MOSI1 (can be rerouted to PH1)– PP0 MISO1 (can be rerouted to PH0)
• By default, the SPI2 shares the use of the upper 4 Port P pins:– PP6 SS2 (can be rerouted to PH7)– PP7 SCK2 (can be rerouted to PH6)– PP5 MOSI2 (can be rerouted to PH5)– PP4 MISO2 (can be rerouted to PH4)
• It is important to make sure that there is no conflict in the use of signal pins when making rerouting decision.
Module Routing Register
ECE 4510/5530
7
• The MODRR configures the re-routing of CAN0, CAN4, SPI0, SPI1, and SPI2 on defined port pins.
SPI0 Pin Selection MODRR[4]
ECE 4510/5530
8
Default
Alternate
SPI1 and SPI2Pin Selection MODRR[5:6]
ECE 4510/5530
9
Default
Alternate
Chapter 11: Inter-Integrated Circuit (I2C)
ECE 4510/5530
10
ECE 2510 11
Inter-Integrated Circuit (I2C)
• Inter-Integrated Circuit (I2C) Interface– Synchronous (fast, but with pull-ups required)– More than 8-bits at a time– Multiple devices can communicate using the same serial lines– Bi-directional data transfer– Does not require a single master
Byte Level Transfer
• Every byte put on the SDA line must be eight bits long. The number of bytes that can be transmitted per transfer is unrestricted. Each byte must be followed by an Acknowledge bit. Data is transferred with the Most Significant Bit (MSB) first (see Figure 6). If a slave cannot receive or transmit another complete byte of data until it has performed some other function, it can hold the clock line SCL LOW to force the master into a wait state. Data transfer then continues when the slave is ready for another byte of data and releases clock line SCL.
NXP, I2C-bus specification and user manual, Rev. 5 — 9 October 2012http://www.nxp.com/documents/user_manual/UM10204.pdf
ECE 4510/5530
12
Data Transfer Format: Write
• Master transmitter to slave receiver – shown in Figure 11.10.
Data Transfer Format: Read
• Master reads slave immediately after the first byte (address byte) – shown in Figure 11.11.
An Overview of the HCS12 I2C Module
• The HCS12 I2C implements a subset of the I2C protocol.– Provides interrupts on start and stop bits in hardware to
determine if the I2C bus is free.– Supports only 7-bit addressing– Supports 100 kbps baud rate but requires the user to
limit the slew rate to no higher than 100 ns if the 400 kbps baud is to be used.
– Limit the maximum bus capacitance to 400 pF for all conditions.
IIC Block Diagram
Registers
Example 1
• Case 1: 100 kHz– SCL divider = 240– From table in text: MUL = 1, IBC[7:0]=0x1F
• SDA Hold = 33 clocks (1.375 usec < 3.45 usec max spec)• SCL Hold (start) = 118 clocks (4.92 usec > 4.0 usec min spec)• SCL Hold (stop) = 121 clocks (5.04 usec > 4.0 usec min spec)
• Notes:– 4 usec min more than 96 clocks– 3.45 usec max less than 82.8 clocks
– 4.7 usec min from spec more than 112.8 clocks
ECE 4510/5530
17
I2C Initialization
• Compute an appropriate value and write it into the IBFD register.• Load a value into the IBAD register if the MCU may operate in slave mode.• Set the IBEN bit of the IBCR register to enable I2C module.• Modify the bits of the IBCR register to select master/slave mode,
transmit/receive mode, and interrupt enable mode
void openI2C (char ibc, char i2c_ID){
IBCR = IBEN; /* enable I2C module, slave receive */IBFD = 0x1F; /* set up I2C baud rate */IBAD = i2c_ID; /* set up slave address */IBCR &= ~IBIE; /* disable I2C interrupt */IBCR |= IBSWAI; /* disable I2C in wait mode */
}
ECE 4510/5530
18
I2C Master Addressing
• Check to insure the bus is not busy (IBSR bit IBB).• Send start condition as master (IBCR bits MSSL and Transmit) • Send address and wait for the transmission to complete.• Modify the bits of the IBCR register to select master/slave mode,
transmit/receive mode, and interrupt enable mode
char sendSlaveID (char cx char RdWrn){
while (IBSR&IBB); /* wait until I2C bus is idle */IBCR |= TXRX+MSSL; /* generate a start condition */IBDR = cx | RdWrn; /* send out the slave address with R/W bit */while(!(IBSR & IBIF)); /* wait for address transmission to complete */IBSR = IBIF; /* clear IBIF flag */return(IBSR & RXAK); /* return the status of the acknowledge */
}
ECE 4510/5530
19
I2C Master Sending Byte
• Check to insure the address acknowledge was received• Send data and wait for the transmission to complete.• Send Stop Condition
if(sendSlaveID(address_isc_device 0x00)) {
IBCR &= ~MSSL; /* generate stop condition */error_condition ….
}else{
IBDR = write_data; /* send out the value cx */while (!(IBSR & IBIF)); /* wait until the byte is shifted out */IBSR = IBIF; /* clear the IBIF flag */if(IBSR & RXAK) ACK_ERR = 1; /* status of the acknowledge */IBCR &= ~MSSL; /* generate stop condition */
}ECE 4510/5530
20
I2C Master Reading Byte
• Check to insure the address acknowledge was received• Place device in receive mode and perform “dummy read”• Receive and provide NACK to end communications.• Send Stop Conditionif(sendSlaveID(address_isc_device 0x01)) {
IBCR &= ~MSSL; /* generate stop condition */error_condition ….
}else{
IBCR &= ~(TXRX + TXAK); /* prepare to receive and acknowledge */IBCR |= TXAK; /* prepare to not acknowledge */dummy = IBDR; /* a dummy read */while(!(IBSR & IBIF)); /* wait for the byte to shift in */IBSR = IBIF; /* clear the IBIF flag */IBCR &= ~MSSL; /* generate stop condition */buf = IBDR; /* place the received byte in buf */
}
ECE 4510/5530
21
Suggested Code Routines
• Transmit one byte• Transmit multiple bytes• Receive one byte• Receive multiple bytes
ECE 4510/5530
22
I2C Real-Time Clock/Calendar MCP7940M
Features• Real-Time Clock/Calendar (RTCC):
– Hours, Minutes, Seconds, Day of Week, Day, Month and Year
– Dual alarm with single output
• On-Chip Digital Trimming/Calibration:– Range -127 to +127 ppm, Resolution 1 ppm
• Programmable Open-Drain Output Control:– CLKOUT with 4 selectable frequencies– Alarm output
• 64 Bytes SRAM• Low-Power CMOS Technology:
– Dynamic Current: 400 �A max write
• 100 kHz and 400 kHz Compatibility• ESD Protection >4,000V• Packages include 8-Lead SOIC, TSSOP,
2x3 TDFN, MSOP and PDIP• Temperature Ranges:
– Industrial (I): -40°C to +85°C
Typical Application Schematic
MCP7940M Address Map
• Time and Data Region (same as text )• Configuration (similar to text )• Calibration• Alarm 0• Alarm 1• 64 Byte SRAM
Clock/Calendars are often designed with battery backup. Therefore, the 64 Byte SRAM
is available for user nonvolatile storage.
MCP7940M Address Map Detail
Same as textbook
Matches clock
structure
Matches clock
structure
Extra bits
MCP7940M Control Register
• Bit 7 is the OUT bit. This sets the logic level on the MFP when not using this as a square wave output.
• Bit 6 is the SQWE bit. Setting this bit enables the divided output from the crystal oscillator.
• Bits 5:4 determine which alarms are active.– 00 – No Alarms are active– 01 – Alarm 0 is active– 10 – Alarm 1 is active– 11 – Both Alarms are active
• Bit 3 is the EXTOSC enable bit. Setting this bit will allow an external 32.768 kHz signal to drive the RTCC registers, eliminating the need for an external crystal.
• Bit 2:0 sets the internal divider for the 32.768 kHz oscillator to be driven to the MFP. The duty cycle is 50%. The output is responsive to the Calibration register. The following frequencies are available:
– 000 – 1 Hz– 001 – 4.096 kHz– 010 – 8.192 kHz– 011 – 32.768 kHz– 1xx enables the Cal output function. Cal output appears on MFP if SQWE is set (64 Hz Nominal). See Section
4.2.1 “Calibration” for more details.
MCP7940M Calibration Register
• Register 0x08h is the Calibration register. • This is an 8-bit register that is used to add or subtract
clocks from the RTCC counter every minute. The MSB is the sign bit and indicates if the count should be added or subtracted. The remaining 7 bits, with each bit adding or subtracting 2 clocks, give the user the ability to add or subtract up to 254 clocks per minute.
MCP7940M Alarms
• 0x07h – Is the Control register.– Bits 5:4 determine which alarms are active.
• 00 – No Alarms are active• 01 – Alarm 0 is active• 10 – Alarm 1 is active• 11 – Both Alarms are active
• Locations 0x0Dh and 0x14h have additional bits for alarm configuration.– ALMxPOL: This bit specifies the level that the MFP will drive when the alarm is
triggered. • ALM2POL is a copy of ALM1POL. The default state of the MFP when used for alarms is
the inverse of ALM1POL.– ALMxIF: This is the Alarm Interrupt Fag. This bit is set in hardware if the alarm
was triggered. The bit is cleared in software.– ALMxC2:0: These Configuration bits determine the alarm match. The logic will trigger the
alarm based on one of the following match conditions• 000 – Seconds match• 001 – Minutes match• 010 – Hours match (takes into account 12/24 hour)• 011 – Matches the current day, interrupt at 12.00.00 a.m.• 100 – Date• 111 – Seconds, Minutes, Hour, Day, Date, Month
Crystal Spec and Design Note p. 14
• This is a description of the capacitor selection when using an external crystal.
• We are not going to bother with this as it should work without it, but …to configure for the highest accuracy and stability, you would normally use the capacitors shown.
ECE 4510/5530
30
MCP7940M I2C Data Transfer
• MCP7940M supports both 100 kHz and 400 kHz data transfer.
• The device address (ID) of the MCP7940M is 1101111.
Example 11.3
• Write a function to configure the DS1307 to operate with the following setting:– SQWOUT output enabled– SQWOUT output set to 1 Hz– SQWOUT idle high when it is disabled– Control byte passed in B
• Solution: char openRTCC(char ctrl){
char status;status = sendSlaveID(0xDE 0x00); /* send out DS1307's ID and write*/if (status) return -1; /* if did not acknowledge, return error code */IBDR = 0x07; /* send out control register address */while(!(IBSR & IBIF)); /* wait for end of transmission */IBSR = IBIF; /* clear IBIF flag */if (IBSR & RXAK) return -1; /* if did not acknowledge, return error code */IBDR = ctrl; /* send out control byte */while(!(IBSR & IBIF));IBSR = IBIF;if (IBSR & RXAK) return -1; /* if did not acknowledge, return error code */IBCR &= ~MSSL; /* generate a stop condition */return 0;
}
Example 11.5
• Write a function to send the time and calendar information to the DS1307. – The time and calendar information is pointed to by X. The device ID and the starting register address are
passed in A and B, respectively. X points to the value of year and the second’s value is located at [X]+6.
• Solution: char sendTime (char *ptr, char ID){
char i;sendSlaveID(0xDE 0x00); /* send ID to DS1307 */if(IBSR & RXAK) return -1; /* did DS1307 acknowledge? */IBDR = 0x00; /* send out seconds register address */while(!(IBSR & IBIF));IBSR = IBIF; /* clear IBIF flag */if(IBSR & RXAK) return -1;for(i = 6; i >= 0; i--) { /* send year first, send second last */
IBDR = *(ptr+i);while(!(IBSR&IBIF));IBSR = IBIF;if(IBSR & RXAK) return -1;
}IBCR &= ~MSSL; /* generate a stop condition */ return 0;
}
Example 11.6
• Write a C function to read the time of day from the DS1307 and save it in the array cur_time[0…6].
• Solution:char readTime(char cx){
char i, temp;sendSlaveID(0xDE, 0x00); /* generate a start condition and send DS1307's ID */if (IBSR & RXAK) return -1; /* if did not respond, return error code *IBDR = cx; /* send address of seconds register */while(!(IBSR & IBIF));IBSR = IBIF; /* clear the IBIF flag */if (IBSR & RXAK) return -1; /* if did not respond, return error code */
IBCR |= RSTA; /* generate a restart condition */IBDR = 0xDE | 0x01; /* send ID and set R/W flag to read */while(!(IBSR & IBIF));IBSR = IBIF;if (IBSR & RXAK) return -1; /* if DS1307 did not respond, return error code */
IBCR &= ~(TXRX + TXAK); /* prepare to receive and acknowledge */temp = IBDR; /* a dummy read to trigger 9 clock pulses */for (i = 0; i < 5; i++) {while(!(IBSR & IBIF)); /* wait for a byte to shift in */
IBSR = IBIF; /* clear the IBIF flag */cur_time[i] = IBDR; /* save the current time in buffer */
} /* also initiate the next read */while (!(IBSR & IBIF)); /* wait for the receipt of cur_time[5] */IBSR = IBIF; /* clear IBIF flag */IBCR |= TXAK; /* not to acknowledge cur_time[6] */cur_time[5] = IBDR; /* save cur_time[5] and initiate next read */while (!(IBSR & IBIF));IBSR = IBIF;IBCR &= ~MSSL; /* generate stop condition */cur_time[6] = IBDR;return 0;
}
Example 11.6 (cont.)
void formatTime(void){
char temp3;temp3 = cur_time[3] & 0x07; /* extract day-of-week */if (cur_time[2] & 0x40) { /* if 12-hour mode is used */hms[0] = 0x30 + ((cur_time[2] & 0x10) >> 4); /* tens hour digit */hms[1] = 0x30 + (cur_time[2] & 0x0F); /* ones hour digit */hms[2] = ':';hms[3] = 0x30 + (cur_time[1] >> 4); /* tens minute digit */hms[4] = 0x30 + (cur_time[1] & 0x0F); /* ones minute digit */hms[5] = ':';hms[6] = 0x30 + ((cur_time[0] & 0x70) >> 4); /* tens second digit */hms[7] = 0x30 + (cur_time[0] & 0x0F); /* ones second digit */hms[8] = ':';if (cur_time[2] & 0x20)
hms[9] = 'P';else
hms[9] = 'A';hms[10] = 'M';hms[11] = 0; /* terminate the string with a NULL */
Format Received Time Information
switch(temp3) { /* convert to day of week */case 1: mdy[0] = 'S';
mdy[1] = 'U';break;
case 2: mdy[0] = 'M';mdy[1] = 'O';break;
case 3: mdy[0] = 'T';mdy[1] = 'U';break;
case 4: mdy[0] = 'W';mdy[1] = 'E';break;
case 5: mdy[0] = 'T';mdy[1] = 'H';break;
case 6: mdy[0] = 'F';mdy[1] = 'R';break;
case 7: mdy[0] = 'S';mdy[1] = 'A';break;
default: mdy[0] = 0x20; /* space */mdy[1] = 0x20;break;
}mdy[2] = ':';mdy[3] = 0x30 + (cur_time[5] >> 4); /* month */mdy[4] = 0x30 + (cur_time[5] & 0x0F);mdy[5] = ':';mdy[6] = 0x30 + (cur_time[4] >> 4); /* date */mdy[7] = 0x30 + (cur_time[4] & 0x0F);mdy[8] = ':';mdy[9] = 0x30 + (cur_time[6] >> 4); /* year */mdy[10] = 0x30 + (cur_time[6] & 0x0F);mdy[11] = 0; /* NULL character */}else {/* 24-hour mode */hms[0] = 0x30 + ((cur_time[2] & 0x30)>>4); /* hours */hms[1] = 0x30 + (cur_time[2] & 0x0F);hms[2] = ':';hms[3] = 0x30 + (cur_time[1] >> 4); /* minutes */hms[4] = 0x30 + (cur_time[1] & 0x0F);hms[5] = ':';
hms[6] = 0x30 + ((cur_time[0] & 0x70)>>4); /* seconds */hms[7] = 0x30 + (cur_time[0] & 0x0F);hms[8] = ':';switch(temp3) { /* convert to day of week */
case 1: hms[9] = 'S';hms[10] = 'U';break;
case 2: hms[9] = 'M';hms[10] = 'O';break;
case 3: hms[9] = 'T';hms[10] = 'U';break;
case 4: hms[9] = 'W';hms[10] = 'E';break;
case 5: hms[9] = 'T';hms[10] = 'H';break;
case 6: hms[9] = 'F';hms[10] = 'R';break;
case 7: hms[9] = 'S';hms[10] = 'A';break;
default: hms[9] = 0x20; /* space */hms[10] = 0x20;break;
}hms[11] = 0; /* NULL character */mdy[0] = 0x30 + (cur_time[5] >> 4); /* month */mdy[1] = 0x30 + (cur_time[5] & 0x0F);mdy[2] = ':';mdy[3] = 0x30 + (cur_time[4] >> 4); /* date */mdy[4] = 0x30 + (cur_time[4] & 0x0F);mdy[5] = ':';mdy[6] = 0x30 + (cur_time[6] >> 4); /* year */mdy[7] = 0x30 + (cur_time[6] & 0x0F);mdy[8] = 0; /* NULL character */}
}