Hello, I'm trying to talk to an OLED display (ssd1306) on my custom board via i2c with my tm4c1294ncpdt. ) I seem to be having an issue with the library (version TivaWare_C_Series-2.2.0.295). I have gotten to the point in my configuration where I can see some basic i2c data on my scope but it always seems to send to an address of 0x7F not 0x3C (i have also tried 0x78, 0x3D, 0x7A all output 0x7F) and no data. (and yes I have pull up resistors installed if that a question, I found that 1k seems to make the clock rise really sharp).
UNLESS i use an address of 0x00, then it seems to spit data of 0x7F
Here is the code for my config.
#include <stdbool.h> #include <stdint.h> #include <stdio.h> #include "inc/hw_memmap.h" #include "driverlib/gpio.h" #include "driverlib/i2c.h" #include "driverlib/sysctl.h" #include "inc/hw_ints.h" #include "inc/hw_nvic.h" #include "inc/hw_types.h" #include "driverlib/interrupt.h" #include "driverlib/pin_map.h" #include "driverlib/systick.h" #include "driverlib/rom.h" #include "driverlib/rom_map.h" #include "utils/uartstdio.h" #include "i2c.h" #include "ssd1306.h" uint32_t g_ui32SysClock; void I2C_2_config() { // Configure I2C3 for pins PN4 and PN5 SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C2); SysCtlPeripheralReset(SYSCTL_PERIPH_I2C2); SysCtlPeripheralEnable(SYSCTL_PERIPH_GPION); while (!SysCtlPeripheralReady(SYSCTL_PERIPH_I2C2)){ } while(!SysCtlPeripheralReady(SYSCTL_PERIPH_GPION)){ } GPIOPinConfigure(GPIO_PN5_I2C2SCL); GPIOPinConfigure(GPIO_PN4_I2C2SDA); GPIOPinTypeI2CSCL(GPIO_PORTN_BASE, GPIO_PIN_5); GPIOPinTypeI2C(GPIO_PORTN_BASE, GPIO_PIN_4); //config for sda line (heard this in a thread somewhere) GPIOPadConfigSet(GPIO_PORTN_BASE, GPIO_PIN_4, GPIO_STRENGTH_8MA, GPIO_PIN_TYPE_OD); //also heard this in a thread somewhere I2CMasterGlitchFilterConfigSet(I2C2_BASE, I2C_MASTER_GLITCH_FILTER_8); I2CMasterInitExpClk(I2C2_BASE, g_ui32SysClock, false); //the true false doesnt seem to change the speed from 100k to 400k I2CMasterTimeoutSet(I2C2_BASE, 0x7D); I2CMasterEnable(I2C2_BASE); } void I2C_sendSingleByte(uint8_t slave_addr, char data) { I2CMasterSlaveAddrSet(I2C2_BASE, slave_addr, false); I2CMasterDataPut(I2C2_BASE, data); I2CMasterControl(I2C2_BASE, I2C_MASTER_CMD_SINGLE_SEND); while (I2CMasterBusy(I2C2_BASE)); } int main(void) { g_ui32SysClock = SysCtlClockFreqSet((SYSCTL_OSC_MAIN | SYSCTL_USE_PLL | SYSCTL_CFG_VCO_480), 120000000); I2C_2_config(); while(I2CMasterBusy(I2C2_BASE)); I2C_sendSingleByte(0x00, 0x00); //if i use any address other than 0x00, it actually sends address 0x7F //If i do use address 0x00, then it sends data 0x7F while (1) { } }
Another weird thing that I noticed about this built-in i2c library is that when I use the I2CMasterInitExpClk(I2C2_BASE, g_ui32SysClock, false);, changing the true or false doesn't seem to effect the speed at which the i2c data comes out at. Perhaps this is some sort of bug in the driver?
I have also bit banged my own basic i2c program where I force the correct address and the OLED display seems to respond (when i get the right address, i verified it doesn't do the same pull down stuff if the address is incorrect) as i can tell from the SDA line being pulled down.
And i know its the OLED display pulling the line down because with the same exact code with the OLED display removed, the line isnt pulled down the same way at all.
Here is my bitbang i2c code please ignore the uglyness of the code, just trying to force i2c like bits to verify the goodness of the display.
#include <stdbool.h> #include <stdint.h> #include <stdio.h> #include "inc/hw_memmap.h" #include "driverlib/gpio.h" #include "driverlib/i2c.h" #include "driverlib/sysctl.h" #include "inc/hw_ints.h" #include "inc/hw_nvic.h" #include "inc/hw_types.h" #include "driverlib/interrupt.h" #include "driverlib/pin_map.h" #include "driverlib/systick.h" #include "driverlib/rom.h" #include "driverlib/rom_map.h" #include "utils/uartstdio.h" #include "i2c.h" #include "ssd1306.h" uint32_t g_ui32SysClock; void I2C_2_config() { // Configure I2C3 for pins PN4 and PN5 SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C2); SysCtlPeripheralReset(SYSCTL_PERIPH_I2C2); SysCtlPeripheralEnable(SYSCTL_PERIPH_GPION); GPIOPinConfigure(GPIO_PN5_I2C2SCL); GPIOPinConfigure(GPIO_PN4_I2C2SDA); GPIOPinTypeI2CSCL(GPIO_PORTN_BASE, GPIO_PIN_5); GPIOPinTypeI2C(GPIO_PORTN_BASE, GPIO_PIN_4); I2CMasterInitExpClk(I2C2_BASE, g_ui32SysClock, false); } void I2C_sendSingleByte(uint8_t slave_addr, char data) { I2CMasterSlaveAddrSet(I2C2_BASE, slave_addr, false); I2CMasterDataPut(I2C2_BASE, data); I2CMasterControl(I2C2_BASE, I2C_MASTER_CMD_SINGLE_SEND); while (I2CMasterBusy(I2C2_BASE)); } void I2C_sendMultipleBytes(uint8_t slave_addr, uint8_t numOfBytes, char by[]){ uint8_t i; I2CMasterSlaveAddrSet(I2C2_BASE, slave_addr, false); I2CMasterDataPut(I2C2_BASE, by[0]); I2CMasterControl(I2C2_BASE, I2C_MASTER_CMD_BURST_SEND_START); while(I2CMasterBusy(I2C2_BASE)); for(i = 1; i < numOfBytes - 1; i++){ I2CMasterDataPut(I2C2_BASE, by[i]); I2CMasterControl(I2C2_BASE, I2C_MASTER_CMD_BURST_SEND_CONT); while(I2CMasterBusy(I2C2_BASE)); } I2CMasterDataPut(I2C2_BASE, by[numOfBytes - 1]); I2CMasterControl(I2C2_BASE, I2C_MASTER_CMD_BURST_SEND_FINISH); while(I2CMasterBusy(I2C2_BASE)); } int main(void) { g_ui32SysClock = SysCtlClockFreqSet((SYSCTL_OSC_MAIN | SYSCTL_USE_PLL | SYSCTL_CFG_VCO_480), 120000000); I2C_2_config(); int i; int j; int k; GPIOPinTypeGPIOOutput(GPIO_PORTN_BASE, GPIO_PIN_5); GPIOPinTypeGPIOOutput(GPIO_PORTN_BASE, GPIO_PIN_4); GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_5, GPIO_PIN_5); GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_4, GPIO_PIN_4); int Data = 0x78; GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_4, 0x0); //send 0x78 via SDA for (i = 0x100; i >= 0x1; i = i >> 1) { if ((Data & i) == i) { GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_4, GPIO_PIN_4); } else { GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_4, 0x0); } GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_5, GPIO_PIN_5); GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_5, 0x0); } for(k = 0; k <= 0xF; k++){ GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_4, GPIO_PIN_4); } //send 0xAE via SDA Data = 0xAE; GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_4, 0x0); for (i = 0x100; i >= 0x1; i = i >> 1) { if ((Data & i) == i) { GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_4, GPIO_PIN_4); } else { GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_4, 0x0); } GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_5, GPIO_PIN_5); GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_5, 0x0); } for(k = 0; k <= 0xF; k++){ GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_4, GPIO_PIN_4); } GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_5, GPIO_PIN_5); GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_4, GPIO_PIN_4); while (1) { } }
I'm running out of ideas and am getting a bit frustrated as it seems like everybody else using the i2c drivers and code seems to be getting it to work fairly easily. I'm not sure how my config is different. I have a suspicion that my drivers are to blame, and ive tried using an older version of the tiva library (2.1.4.178) and it does the same stuff.
Thanks, -Sam