Hi Everyone, I would like to share with you a simple bare metal example for the the SC16IS752 to demonstrate NXP Bridge IC for SPI/ I 2 C host to Dual Uart/IrDa/GPIO interface. This example is based on the OM6273 demo board for the SC16752/762. I made this example working with the NXP FRDM-KL25Z development platform. The example shows the device functionality by creating a simple echo transmission, where you are able to read what you just write into the device. This example illustrates: 1. Initialization of the MKL25Z128 MCU (I 2 C and port modules) 2. I 2 C data write and read operations 3. Initialization of the bridge to perform the communication 4. Transmission and the reception done with interrupt technique 5. Visualization of the echo function using the serial terminal 1. As you can see in the FRDM-KL25Z schematics and the image below, I 2 C signals are routed to the I2C1 module (PTC1 and PTC2 pins) of the KL25Z MCU and the INT1 output is connected to the PTA16 pin. The INT1 output of the SC16IS752 is configured as a push-pull active-low output, so the corresponding PTA16 pin configuration is GPIO with an interrupt on falling edge. Therefore, this is the MCU configuration: void MCU_Init(void)
{
//I2C1 module initialization
SIM_SCGC4 |= SIM_SCGC4_I2C1_MASK; // Turn on clock to I2C1 module
SIM_SCGC5 |= SIM_SCGC5_PORTC_MASK; // Turn on clock to Port E module
PORTC_PCR1 = PORT_PCR_MUX(2); // PTC1 pin is I2C1 SCL line
PORTC_PCR2 = PORT_PCR_MUX(2); // PTC2 pin is I2C1 SDA line
I2C1_F = 0x14; // SDA hold time = 2.125us, SCL start hold time = 4.25us, SCL stop hold time = 5.125us
I2C1_C1 = I2C_C1_IICEN_MASK; // Enable I2C1 module
//Configure the PTA16 pin (connected to the IRQ of the SC16IS752) for falling edge interrupts
SIM_SCGC5 |= SIM_SCGC5_PORTA_MASK; // Turn on clock to Port A module
PORTA_PCR16 |= (0|PORT_PCR_ISF_MASK // Clear the interrupt flag
| PORT_PCR_MUX(0x1) // PTA16 is configured as GPIO
| PORT_PCR_IRQC(0xA)); // PTA16 is configured for falling edge interrupts
//Enable PORTA interrupt on NVIC
NVIC_EnableIRQ(PORTA_IRQn); // Enable interrupts
NVIC_ClearPendingIRQ(PORTA_IRQn); // Clear pending interrupts
}
2. To perform the read or write operation we'll make use of an I 2 C library which contains to main functions: void I2C_WriteRegister(unsigned char u8SlaveAddress, unsigned char u8RegisterAddress, /*unsigned*/ char u8Data); unsigned char I2C_ReadRegister(unsigned char u8SlaveAddress, unsigned char u8RegisterAddress) Before any data is transmitted or received, the master must send the address of the receiver via the SDA line. The first byte after the START condition carries the address of the slave device and the read/write bit. Table 32. shows how the SC16IS752/SC16IS762’s address can be selected by using A1 and A0 pins. In the demo board OM6273, these 2 pins are connected to JP4 and JP3 and in this example there are two jumpers plugged so A1 = VDD and A2 = VDD, then the SC16IS752’s address is set to 0x90(Write) and 0x91(Read), and the master communicates with it through this address. The second parameter in the read or write function is the internal register address, these are defined in the SC16IS752.h attached to this document and explained with greater detail in the SC16IS752 datasheet. 3. The SC16IS752 is set to work at 115, 200 baud/s , the Receive Holding Register interrupt is enabled and routed to the INT1 pin that is configured to be a push-pull, active-low output. The registers are shift 3 positions left because the UART's internal register select are the bits 3:0, as shown in table 33. In the example channel 0 is used. This initialization is based in the application notes AN10587 and AN10462, where is possible to find additional information in regards the SC16IS752 // Program channel A for I2C-UART
void SC16IS752_Init_ChA (void) {
I2C_WriteRegister(SC16IS752_ADDRESS, LCR_REG << 3, 0x80); // 0x80 when LCR[7] = 1 DLL and DLH are accessible
I2C_WriteRegister(SC16IS752_ADDRESS, DLL_REG << 3, 0x08); // 0x08 = 115,200 baud rate when XTal = 14.7456 MHz
I2C_WriteRegister(SC16IS752_ADDRESS, DLH_REG << 3, 0x00); // 0x00 = 115,200 baud rate when XTal = 14.7456 MHz
I2C_WriteRegister(SC16IS752_ADDRESS, LCR_REG << 3, 0xBF); // Access special features register
I2C_WriteRegister(SC16IS752_ADDRESS, EFR_REG << 3, 0x10); // enable enhanced functions
I2C_WriteRegister(SC16IS752_ADDRESS, LCR_REG << 3, 0x03); // 8 data bit, 1 stop bit, no parity
I2C_WriteRegister(SC16IS752_ADDRESS, IODIR_REG << 3, 0xFF); // set GPIO [7:0] to output (input by default)
I2C_WriteRegister(SC16IS752_ADDRESS, IOSTATE_REG << 3, 0x00); // set GPIO [7:0] to 0x00 (Turn LEDs on)
I2C_WriteRegister(SC16IS752_ADDRESS, IER_REG << 3, 0x01); // enable Rx data ready interrupt
} 4. In the interrupt service routine the program reads the interrupt identification register, and it's ready to add a different task for each interrupt, for now it simply enables the data ready flag when the interrupt was generated by the RHR. It also cleans the flag that generated the interrupt. We also have the write function and the read function of the SC16IS752, these two functions access the corresponding THR or RHR registers. void PORTA_IRQHandler()
{
//Interrupt service routine
Interrupt_Source iir = I2C_ReadRegister(SC16IS752_ADDRESS, IIR_REG << 3); //read IIR to retrieve the interrupt source
// IIR[5:1] 5-bit encoded interrupt
switch(iir & 0x3E) {
case RHR: DataReady = 1; break;
default : break;
}
PORTA_PCR16 |= PORT_PCR_ISF_MASK; // Clear the interrupt flag
}
void writeSC16IS752(char data) {
I2C_WriteRegister(SC16IS752_ADDRESS, FCR_REG <<3, 0x04); //clears the contents of the transmit FIFO
while(!(I2C_ReadRegister(SC16IS752_ADDRESS, LSR_REG <<3) & 0x40)); //Is it able to transmit? - Poll Transmit empty indicator
I2C_WriteRegister(SC16IS752_ADDRESS, THR_REG << 3, data); //Write to the transmit holding register to start transmission
}
unsigned char readSC16IS752(void) {
return I2C_ReadRegister(SC16IS752_ADDRESS,RHR_REG); //Read receive holding register
}
5. We connect the I 2 C lines with each other in the board, JP6 contains INT1, SDA and SCL in that order, then P1 is connected to EVBUSB2SER (USB to serial device), and this last one to a computer. In the computer must be installed a serial terminal, for this example Teraterm is used We set up Tera Term going to Setup > Serial Port and then select corresponding port to the EVBUSB2SER and baud rate 115,200 This is the main, that should be executed to perform the echo function char DataReady;
int main(void)
{
unsigned char echo = 0;
MCU_Init();
Pause(500000);
SC16IS752_Init_ChA();
for (;;) {
if(DataReady) {
DataReady = 0;
echo = readSC16IS752(); //Read RHR, since FIFO is disable it only reads the first location
writeSC16IS752(echo); //Send back the value received
}
}
return 0;
} After this, every character written in the serial terminal will appear in the serial terminal as you were writing in the command prompt Attached you can find the complete source code written using KDS IDE and some other relevant documentation If there are any questions regarding this simple application, do not hesitate to ask below. Your feedback or suggestions are also welcome. Thanks to a major collaborator for this document david_diaz. Regards, Darío Arias
View full article