HAL_StatusTypeDef HAL_I2C_Mem_Write(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout)
首先介绍下这个函数,官方的I2C写函数(注意这个没有用到中断,DMA,属于阻塞类发送的)
- *hi2c: I2C设备号指针,设置使用的是那个IIC 例:&hi2c2
- DevAddress: 从设备地址 从设备的IIC地址 例E2PROM的设备地址 0xA0
- MemAddress: 从机寄存器地址 ,每写入一个字节数据,地址就会自动+1
- MemAddSize: 从机寄存器地址字节长度 8位或16位
- *pData: 需要写入的的数据的起始地址
- Size: 传输数据的大小 多少个字节
- Timeout: 最大读取时间,超过时间将自动退出函数
void OLED_WR_CMD(uint8_t cmd)//向OLED写命令 { HAL_I2C_Mem_Write(&hi2c1 ,0x78,0x00,I2C_MEMADD_SIZE_8BIT,&cmd,1,0x100); } void OLED_WR_DATA(uint8_t data)//向OLED写数据 { HAL_I2C_Mem_Write(&hi2c1 ,0x78,0x40,I2C_MEMADD_SIZE_8BIT,&data,1,0x100); }
我这里是一个字节一个字节的传送,所有字节大小填1
void OLED_DISPLAY_CLEAR(void){//清屏操作 uint8_t j,t; for(t=0xB0;t<0xB8;t++){ //设置起始页地址为0xB0 //I2C_SAND_BYTE(OLED0561_ADD,COM,t); //页地址(从0xB0到0xB7) //I2C_SAND_BYTE(OLED0561_ADD,COM,0x10); //起始列地址的高4位 //I2C_SAND_BYTE(OLED0561_ADD,COM,0x00); //起始列地址的低4位 OLED_WR_CMD(t); OLED_WR_CMD(0x10); OLED_WR_CMD(0x00); for(j=0;j<132;j++){ //整页内容填充 //I2C_SAND_BYTE(OLED0561_ADD,DAT,0x00); OLED_WR_DATA(0); } } }
上面注释掉的代码是使用标准库的函数,无视了
void OLED_DISPLAY_8x16(uint8_t x, //显示汉字的页坐标(从0到7)(此处不可修改) uint8_t y, //显示汉字的列坐标(从0到63) uint16_t w){ //要显示汉字的编号 uint8_t j,t,c=0; uint8_t a,b,d,e; y=y+2; //因OLED屏的内置驱动芯片是从0x02列作为屏上最左一列,所以要加上偏移量 for(t=0;t<2;t++){ //I2C_SAND_BYTE(OLED0561_ADD,COM,0xb0+x); //页地址(从0xB0到0xB7) //I2C_SAND_BYTE(OLED0561_ADD,COM,y/16+0x10); //起始列地址的高4位 //I2C_SAND_BYTE(OLED0561_ADD,COM,y%16); //起始列地址的低4位 OLED_WR_CMD(0xb0+x); OLED_WR_CMD(y/16+0x10); OLED_WR_CMD(y%16); for(j=0;j<8;j++){ //整页内容填充 //I2C_SAND_BYTE(OLED0561_ADD,DAT,ASCII_8x16[(w*16)+c-512]);//为了和ASII表对应要减512 OLED_WR_DATA(ASCII_8x16[(w*16)+c-512]); c++;}x++; //页地址加1 } } //向LCM发送一个字符串,长度64字符之内。 //应用:OLED_DISPLAY_8_16_BUFFER(0," KingZhan"); void OLED_DISPLAY_8x16_BUFFER(uint8_t row,uint8_t *str){ uint8_t r=0; while(*str != '\0'){ OLED_DISPLAY_8x16(row,r*8,*str++); r++; } }
完成