【Renesas RA4E1 Evaluation Board】IIC and OLED SSD1306 Test
[Copy link]
IIC is a common bus, which is widely used. It can connect devices with just two signal lines, but the programming of this bus is more complicated than other communication methods. RA4E1 is also designed with IIC bus, but RA4E1 has two peripherals, one is the traditional dedicated IIC device, and the other is the universal serial device (SCI). This test is the master mode of the dedicated IIC device, and the specific settings are as follows:
The communication mode can use Fast mode, the IIC device uses an OLED display, the controller interface uses IIC mode, and the address uses 0x3C, which is given by the settings of the SSD1306 control.
The test of IIC device was not smooth. I tried many times but failed. I used STM32 driver solution and modified it many times but failed. I couldn't understand the last parameter of R_IIC_MASTER_Write(), reset, until I saw a post on the Internet and successfully completed the test. The main program below is in oled.c.
/*
* oled.c
*
* Created on: 2021?10?6?
* Author: Administrator
*/
#include "oled.h"
#include "oledfont.h"
#include "hal_data.h"
#include "stdint.h"
uint8_t CMD_Data[]={
0xAE,
0x00,
0x10,
0x40,
0xB0,
0x81,
0xFF,
0xA1,
0xA6,
0xA8,
0x3F,
0xC8,
0xD3,
0x00,
0xD5,
0x80,
0xD8,
0x05,
0xD9,
0xF1,
0xDA,
0x12,
0xD8,
0x30,
0x8D,
0x14,
0xAF
};
extern fsp_err_t err;
extern int timeout_ms;
extern i2c_master_event_t i2c_event ;
void WriteCmd(void)
{
uint8_t i = 0;
uint8_t ii[2]={0x00,0x00};
for(i=0;i<27;i++)
{
ii[1]=CMD_Data[i];
err = R_IIC_MASTER_Write(&g_i2c_master0_ctrl, ii, 0x02, true);
assert(FSP_SUCCESS == err);
/* Since there is nothing else to do, block until Callback triggers*/
while ((I2C_MASTER_EVENT_TX_COMPLETE != i2c_event) && timeout_ms>0)
{
R_BSP_SoftwareDelay(1U, BSP_DELAY_UNITS_MICROSECONDS);
timeout_ms--;
}
if (I2C_MASTER_EVENT_ABORTED == i2c_event)
{
__BKPT(0);
}
/* Read data back from the I2C slave */
i2c_event = I2C_MASTER_EVENT_ABORTED;
timeout_ms = 100;
}
}
void OLED_WR_CMD(uint8_t cmd)
{
uint8_t ii[2]={0x00,0x00};
ii[1]=cmd;
err = R_IIC_MASTER_Write(&g_i2c_master0_ctrl, ii, 0x02, true);
assert(FSP_SUCCESS == err);
/* Since there is nothing else to do, block until Callback triggers*/
//while ((I2C_MASTER_EVENT_TX_COMPLETE != i2c_event) && timeout_ms)
while ((I2C_MASTER_EVENT_TX_COMPLETE != i2c_event) && timeout_ms>0)
{
R_BSP_SoftwareDelay(1U, BSP_DELAY_UNITS_MICROSECONDS);
timeout_ms--;
}
if (I2C_MASTER_EVENT_ABORTED == i2c_event)
{
__BKPT(0);
}
/* Read data back from the I2C slave */
i2c_event = I2C_MASTER_EVENT_ABORTED;
timeout_ms = 100;
}
void OLED_WR_DATA(uint8_t data)
{
uint8_t ii[2]={0x40,0x00};
ii[1]=data;
err = R_IIC_MASTER_Write(&g_i2c_master0_ctrl, ii, 0x02, true);
assert(FSP_SUCCESS == err);
/* Since there is nothing else to do, block until Callback triggers*/
while ((I2C_MASTER_EVENT_TX_COMPLETE != i2c_event) && timeout_ms>0)
{
R_BSP_SoftwareDelay(1U, BSP_DELAY_UNITS_MICROSECONDS);
timeout_ms--;
}
if (I2C_MASTER_EVENT_ABORTED == i2c_event)
{
__BKPT(0);
}
/* Read data back from the I2C slave */
i2c_event = I2C_MASTER_EVENT_ABORTED;
timeout_ms = 100;
}
void OLED_Clear(void)
{
uint8_t i,n;
for(i=0;i<8;i++)
{
OLED_WR_CMD(0xb0+i);//
OLED_WR_CMD (0x00); //
OLED_WR_CMD (0x10); //
for(n=0;n<128;n++)
OLED_WR_DATA(0);//
}
void OLED_Display_On(void)
{
OLED_WR_CMD(0X8D); //SET DCDC??
OLED_WR_CMD(0X14); //DCDC ON
OLED_WR_CMD(0XAF); //DISPLAY ON
}
void OLED_Display_Off(void)
{
OLED_WR_CMD(0X8D); //SET DCDC??
OLED_WR_CMD(0X10); //DCDC OFF
OLED_WR_CMD(0XAE); //DISPLAY OFF
}
void OLED_Set_Pos(uint8_t x, uint8_t y)
{
OLED_WR_CMD(0xb0+y);
OLED_WR_CMD(((x&0xf0)>>4)|0x10);
OLED_WR_CMD(x&0x0f);
}
void OLED_On(void)
{
uint8_t i,n;
for(i=0;i<8;i++)
{
OLED_WR_CMD(0xb0+i);
OLED_WR_CMD(0x00);
OLED_WR_CMD(0x10);
for(n=0;n<128;n++)
OLED_WR_DATA(1);
}
}
unsigned int oled_pow(uint8_t m,uint8_t n)
{
unsigned int result=1;
while(n--)result*=m;
return result;
}
void OLED_ShowNum(uint8_t x,uint8_t y,unsigned int num,uint8_t len,uint8_t size2)
{
uint8_t t,temp;
uint8_t enshow=0;
for(t=0;t<len;t++)
{
temp=(num/oled_pow(10,len-t-1))%10;
if(enshow==0&&t<(len-1))
{
if(temp==0)
{
OLED_ShowChar(x+(size2/2)*t,y,' ',size2);
continue;
}else enshow=1;
}
OLED_ShowChar(x+(size2/2)*t,y,temp+'0',size2);
}
}
void OLED_ShowChar(uint8_t x,uint8_t y,uint8_t chr,uint8_t Char_Size)
{
unsigned char c=0,i=0;
c=chr-' ';
if(x>128-1)
{
x=0;
y=y+2;
}
if(Char_Size ==16)
{
OLED_Set_Pos(x,y);
for(i=0;i<8;i++)
OLED_WR_DATA(F8X16[c*16+i]);
OLED_Set_Pos(x,y+1);
for(i=0;i<8;i++)
OLED_WR_DATA(F8X16[c*16+i+8]);
}
else {
OLED_Set_Pos(x,y);
for(i=0;i<6;i++)
OLED_WR_DATA(F6x8[c][i]);
}
}
void OLED_ShowString(uint8_t x,uint8_t y,uint8_t *chr,uint8_t Char_Size)
{
unsigned char j=0;
while (chr[j]!='\0')
{
OLED_ShowChar(x,y,chr[j],Char_Size);
x+=8;
if(x>120){x=0;y+=2;}
j++;
}
}
void OLED_ShowCHinese(uint8_t x,uint8_t y,uint8_t no)
{
uint8_t t,adder;
OLED_Set_Pos(x,y);
for(t=0;t<16;t++)
{
OLED_WR_DATA(Hzk1[2*no][t]);
adder+=1;
}
OLED_Set_Pos(x,y+1);
for(t=0;t<16;t++)
{
OLED_WR_DATA(Hzk1[2*no+1][t]);
adder+=1;
}
}
//--------------------------------------------------------------
// Prototype : void OLED_DrawBMP(unsigned char x0,unsigned char y0,unsigned char x1,unsigned char y1,unsigned char BMP[]);
// Calls :
// Parameters : x0,y0 -- ?????(x0:0~127, y0:0~7); x1,y1 -- ?????(???)???(x1:1~128,y1:1~8)
// Description : ??BMP??
//--------------------------------------------------------------
void OLED_DrawBMP(unsigned char x0,unsigned char y0,unsigned char x1,unsigned char y1,unsigned char BMP[])
{
unsigned int j=0;
unsigned char x,y;
if(y1%8==0)
y = y1/8;
else
y = y1/8 + 1;
for(y=y0;y<y1;y++)
{
OLED_Set_Pos(x0,y);
for(x=x0;x<x1;x++)
{
OLED_WR_DATA(BMP[j++]);
}
}
}
The program is to send the command OLED_WR_CMD() and data OLED_WR_DATA() functions. Both functions use the program to send two bytes at a time. The previous references to sending data were all multi-byte versions at a time. The most successful one produced some garbled characters at a time.
The procedure is this,
// Send data
void ssd1306_WriteData(uint8_t* buffer, size_t buff_size) {
//HAL_I2C_Mem_Write(&SSD1306_I2C_PORT, SSD1306_I2C_ADDR, 0x40, 1, buffer, buff_size, HAL_MAX_DELAY);
uint8_t iic_data=0x40;
fsp_err_t err = FSP_SUCCESS;
err = R_IIC_MASTER_Write(&g_i2c_master0_ctrl, &iic_data, ONE_BYTE, false);
//assert(FSP_SUCCESS == err);
/* Since there is nothing else to do, block until Callback triggers*/
while ((I2C_MASTER_EVENT_TX_COMPLETE != i2c_event) && timeout_ms>0)
{
R_BSP_SoftwareDelay(1U, BSP_DELAY_UNITS_MICROSECONDS);
timeout_ms--;
}
// if (I2C_MASTER_EVENT_ABORTED == i2c_event)
// {
// __BKPT(0);
// }
/* Read data back from the I2C slave */
i2c_event = I2C_MASTER_EVENT_ABORTED;
timeout_ms = 100;
err = R_IIC_MASTER_Write(&g_i2c_master0_ctrl, buffer, buff_size, true);
//assert(FSP_SUCCESS == err);
/* Since there is nothing else to do, block until Callback triggers*/
while ((I2C_MASTER_EVENT_TX_COMPLETE != i2c_event) && timeout_ms>0)
{
R_BSP_SoftwareDelay(1U, BSP_DELAY_UNITS_MICROSECONDS);
timeout_ms--;
}
// if (I2C_MASTER_EVENT_ABORTED == i2c_event)
// {
// __BKPT(0);
// }
/* Read data back from the I2C slave */
i2c_event = I2C_MASTER_EVENT_ABORTED;
timeout_ms = 100;
}
If anyone knows why, please give me some advice. I don't know why it doesn't work. Other programs have not been successful.
This test and the previous program only have two bytes of data command at a time. The driver can be driven smoothly, but the speed is more troublesome than multi-byte. The guess is that the multi-byte driver in the middle may have some IIC bus state change.
postscript
The IIC test is the most difficult test for this board. It took me almost two weeks to complete it, but it is not very complete. I also don’t understand the reason for the multi-byte sending.
|