SC16IS752 - Bare metal example project

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

SC16IS752 - Bare metal example project

No ratings

SC16IS752 - Bare metal example project

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/ I2C 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 (I2C and port modules)

2. I2C 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, I2C 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.

                                              KL25Z - Pins.png

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 I2C 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.

                                                Adresses.png

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.

                                                          pastedImage_20.png

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.

pastedImage_83.png

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 I2C 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

SC16IS752.jpg     pastedImage_1.png          USB to ser.jpg

We set up Tera Term going to Setup > Serial Port and then select corresponding port to the EVBUSB2SER and baud rate 115,200

pastedImage_1.png

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

Labels (1)
Attachments
Version history
Last update:
‎09-10-2020 01:56 AM
Updated by: