【瑞萨RA4E1评估板】IIC和OLED SSD1306测试
[复制链接]
IIC是一种常见的总线,这种总线的使用非常广泛,只要使用两条信号线就可以完成设备的连接,但是这种总线的编程要比较其它通讯方式复杂一些。RA4E1也是设计有IIC总线的,但是RA4E1有两种外设,一种是传统的专用IIC设备,一种是通用串行设备(SCI),本次测试的是专用IIC设备的主模式,具体设置如下:
通讯模式可以使用Fast模式,IIC的设备使用的是OLED 显示屏,控制器的接口使用IIC方式,地址使用0x3C,这个地址是由SSD1306控制的设置给定的,
IIC设备的测试很是不顺利,我尝试的很多次,都没有成功。使用了STM32的驱动方案修改了很多次都失败,其中的R_IIC_MASTER_Write()的中的最后参数,reset就是一直不能理解,直到看到一篇网络上的帖子才成功完成测试。下面主要的程序在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++]);
}
}
}
其中的程序是发送命令OLED_WR_CMD()和数据OLED_WR_DATA()函数,这个两个函数都是使用一次发送两个字节的程序,以前参考的发送数据都是一次多字节的版本,最成功的是一次产生了些乱码。
程序是这样的,
// 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;
}
如果有知道原因的请给于指导,不知道为什么不行。其它的程序都没有成功。
本次的测试和以前的程序只有数据命令为一次两个字节。就可以顺利驱动程序,只是速度上要比较多字节的麻烦一些。猜测原因可能是中间的驱动多字节可能有什么IIC总线状态变换的原因。
后记
IIC测试是该板子最困难的测试,我前前后后花了大概快两周的时间才完的,但是也不是很完整,其中的多字节发送也是没有搞清什么原因。
|