一 stm32硬件IIC

硬件IIC特性架构


①通讯引脚
查看对应开发板芯片的原理图可以查看对应IIC外设引脚的位置
这里代码采用的是stm32f103c8t6,硬件IIC的外设引脚为PB6 PB7,故之后的代码中配置PB6 PB7引脚即可

②时钟控制逻辑
时钟控制寄存器CCR,数据手册中有CCR寄存器的模式选择以及快速模式下的占空比选择

计算时钟频率公式:
标准模式 Thigh = CCR x Tpclk1
Tlow = CCR x Tpclk1
快速模式 Thigh = CCR x Tpclk1
Tlow = 2 x CCR x Tpclk1 (DUTY=0)
Thigh = 9 x CCR x Tpclk1
Tlow = 16 x CCR x Tpclk1 (DUTY=1)
例如:配置200kbit/s 即 T = 1/200 000 s(DUTY=0的条件下)
CCR = Thigh/Tpclk1 = 1/200 000 / 3 * 36 000 000 = 60 (APB1系统时钟频率36MHZ)

③数据控制
IIC的SDA信号主要连接到数据移位寄存器上,数据移位寄存器的数据来源及目标是数据寄存器(DR)、地址寄存器(OAR)、PEC寄存器以及SDA数据线。(具体参考上面关于IIC硬件架构图片)
·当向外发送数据的时候,数据移位寄存器以“数据寄存器”为数据源,把数据一位一位地通过SDA信号线发送出去。
·当从外部接收数据的时候,数据移位寄存器把SDA信号线采样到的数据一位一位地存储到”数据寄存器”中。

以7位主发送器为例


Ev事件的寄存器可以到手册上查找对应状态寄存器下面的具体内容
过程大致描述为:发送起始信号,等待Ev5事件,Ev5 = 1,代表起始信号发送完毕
发送接收地址,等待Ev6事件,Ev6 = 1,代表接收地址相匹配
匹配完地址后就是等待Ev8_1事件到来, 这个事件代表移位寄存器为空,可以移动数据到下一位
移动到下一位地址之后就是数据的发送以及等待事件Ev8,循环往复等待数据全部发送完毕,产生EV8_2事件,SR1的TEX位及BTF位被置1,表示通讯结束。

二 OLED屏幕原理以及显示过程

0.96寸oled屏幕(采用IIC通讯)如下所示



0.96寸的oled又叫12864显示屏,分辨率为128*64(这么多个像素点),由128列,64行组成,其中64行又被分为8页,每页8行!

oled屏幕驱动指令

例如:设置开启OLED屏幕根据表中指令可以分3步
①开启显示 0xAF
②电荷泵设置 0x8D
③开启电荷泵 0x14

oled显示

这里显示第一列第一页前5个点 即为0x1f(这里是写入数据,前面的0x1f是写入命令),写完这个数据之后控制器自动移到第二列以相同的方式显示点。不能一次性控制一个点阵,只能一次性控制八位点阵,即一列点阵。这决定了字模选择的取模方式为“列行式“

三 硬件IIC相关代码

oled.c文件(包含配置OLED和硬件IIC)

#include "oled.h"
#include "stm32f10x.h"
#include "codetab.h"          //字库头文件
void I2C_Configuration(void)
{GPIO_InitTypeDef  GPIO_initstruct;     //配置GPIO口结构体  -PB6 -PB7I2C_InitTypeDef  I2C_initstruct;         //配置硬件IIC结构体RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);    //使能对应时钟//PB6 SCL  PB7 SDAGPIO_initstruct.GPIO_Mode = GPIO_Mode_AF_OD;     //复用开漏GPIO_initstruct.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;GPIO_initstruct.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOB,&GPIO_initstruct);I2C_DeInit(I2C1);I2C_initstruct.I2C_Ack =I2C_Ack_Enable;            //IIC应答信号使能I2C_initstruct.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;  //设置从机地址长度为7位I2C_initstruct.I2C_ClockSpeed = 400000;           //设置目标周期 400khzI2C_initstruct.I2C_DutyCycle = I2C_DutyCycle_2; //设置占空比为2:1I2C_initstruct.I2C_Mode = I2C_Mode_I2C;          //设置为IIC模式I2C_initstruct.I2C_OwnAddress1 = 0x30;           //设置主机地址I2C_Init(I2C1, &I2C_initstruct);I2C_Cmd(I2C1, ENABLE);}
//IIC写字节函数
void I2C_WriteByte(uint8_t addr,uint8_t data)
{   //传参数,代表地址和数据while(I2C_GetFlagStatus( I2C1,I2C_FLAG_BUSY));      //等待总线空闲I2C_GenerateSTART(I2C1,ENABLE);                     //IIC发送起始信号while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_MODE_SELECT));//等待EV5=1,具体可以参考手册上面EV5事件I2C_Send7bitAddress(I2C1, OLED_Address, I2C_Direction_Transmitter);//发送从机7位地址while(!I2C_CheckEvent(I2C1,  I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));//等待EV6=1I2C_SendData(I2C1,addr);        //发送地址字节while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTING));   //等待事件EV8I2C_SendData(I2C1,data);       //发送数据字节while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTING));    //等待事件EV8I2C_GenerateSTOP(I2C1,ENABLE); //IIC发送停止信号
}
//IIC写指令函数
void WriteCmd(unsigned char I2C_Command)
{I2C_WriteByte(0x00,I2C_Command);   //从0x00开始写指令
}
void WriteDat(unsigned char I2C_Data)
{I2C_WriteByte(0x40,I2C_Data);  //从0x40开始写数据
}
//OLED初始化函数(厂家提供)
void OLED_Init(void)
{delay_ms(100);WriteCmd(0xAE); //display offWriteCmd(0x20); //Set Memory Addressing Mode    WriteCmd(0x10); //00,Horizontal Addressing Mode;01,Vertical Addressing Mode;10,Page Addressing Mode (RESET);11,InvalidWriteCmd(0xb0);   //Set Page Start Address for Page Addressing Mode,0-7WriteCmd(0xc8);    //Set COM Output Scan DirectionWriteCmd(0x00); //---set low column addressWriteCmd(0x10); //---set high column addressWriteCmd(0x40); //--set start line addressWriteCmd(0x81); //--set contrast control registerWriteCmd(0xff); // 0x00~0xffWriteCmd(0xa1); //--set segment re-map 0 to 127WriteCmd(0xa6); //--set normal displayWriteCmd(0xa8); //--set multiplex ratio(1 to 64)WriteCmd(0x3F); //WriteCmd(0xa4); //0xa4,Output follows RAM content;0xa5,Output ignores RAM contentWriteCmd(0xd3); //-set display offsetWriteCmd(0x00); //-not offsetWriteCmd(0xd5); //--set display clock divide ratio/oscillator frequencyWriteCmd(0xf0); //--set divide ratioWriteCmd(0xd9); //--set pre-charge periodWriteCmd(0x22); //WriteCmd(0xda); //--set com pins hardware configurationWriteCmd(0x12);WriteCmd(0xdb); //--set vcomhWriteCmd(0x20); //0x20,0.77xVccWriteCmd(0x8d); //--set DC-DC enableWriteCmd(0x14); //WriteCmd(0xaf); //--turn on oled panel}
//OLED初始化坐标位置,参数x y分别代表列和页
void OLED_Setpoint(unsigned char x,unsigned char y)
{WriteCmd(0xB0 + y);           //设置页 0xB0代表页为第1页WriteCmd((x&0xf0)>>4|0x10);  //设置列 高四位  获取高四位数据右移动4位并保存,且让第5位为1WriteCmd(x&0x0f|0x01);     //设置列 低四位   保留最后一位数据,并让最后一位数据置1
}
//全屏处理函数
void OLED_Fill(unsigned char Fill_Data)
{unsigned char m,n;for(m=0;m<8;m++)       //页循环{WriteCmd(0xB0+m);    WriteCmd(0X00);     WriteCmd(0X10);     //设置列命令 高四位低四位全部写0,具体效果可查看oled指令表for(n=0;n<128;n++)    {//列循环,写如数据WriteDat(Fill_Data);}}
}
//清屏函数,在全屏处理函数上进行的修改
void OLED_Clear(void)
{OLED_Fill(0x00);
}
//OLED开启函数,前面有提到
void OLED_OPEN(void)
{WriteCmd(0XAF);    //开启显示WriteCmd(0x8D);   //电荷泵设置WriteCmd(0x14);//打开电荷泵
}
//OLED关闭函数
void OLED_CLOSE(void)
{WriteCmd(0XAE);    //关闭显示WriteCmd(0x8D);   //电荷泵设置WriteCmd(0x10);  //关闭电荷泵
}//OLED显示字符串
void OLED_ShowStr(unsigned char x,unsigned char y,unsigned char ch[],unsigned TextSize)
{//传参,x y 分别代表列和页  ch[] 代表字符串  TextSize代表显示字符串大小unsigned char c = 0,i=0,j=0;switch(TextSize){case 1:      //6x8大小的字符串{while(ch[j]!='\0')       //遍历到字符串尾{c = ch[j]-32;        //这句话具体参考字库字母的位置以及对应ASCII码表if(x>126)     //即将写满这一页{x=0;     //回到第一列y++;       //页往下翻}OLED_Setpoint(x,y);//重新置点for(i=0;i<6;i++)WriteDat( F6x8[c][i] );       //写入字库数据x+=6;     j++;      }}break;case 2:             //8x16大小的字符串{while(ch[j]!='\0'){c = ch[j]-32;if(x>120){x=0;     y++;      }OLED_Setpoint(x,y);for(i=0;i<8;i++)  WriteDat(F8X16[c*16+i]);   //上一页写一半OLED_Setpoint(x,y+1);          //将页置一行后继续写,如果没有这句话,效果直接只有字的一半for(i=8;i<16;i++)             //下一页写一半WriteDat(F8X16[c*16+i]);x+=8;j++;}}break;}
}
//OLED显示汉字
void OLED_ShowCharactor(unsigned char x,unsigned char y,unsigned char N)
{unsigned char i = 0;unsigned int addr = 32*N;        //字库汉字的地址OLED_Setpoint(x,y);for(i=0;i<16;i++){WriteDat(F16X16[addr]);addr+=1;}OLED_Setpoint(x,y+1);for(i=0;i<16;i++){WriteDat(F16X16[addr]);addr+=1;}//调用字库一般是要什么汉字就放什么汉字的码进去
}
//oled显示图片
void OLED_ShowPicture(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)      //分页,一页8行y1 = y1/8;elsey1 = y1/8 + 1;for(y=y0;y<y1;y++)     //画点函数{OLED_Setpoint(x0,y);for(x=x0;x<x1;x++){WriteDat(BMP[j++]);}}}

oled.h文件

#ifndef _OLED_H_
#define _OLED_H_        //预编译,防止头文件重复编译,提高编译效率#include "stm32f10x.h"
#define OLED_Address 0x78void I2C_Configuration(void);
void I2C_WriteByte(uint8_t addr,uint8_t data);
void WriteCmd(unsigned char I2C_Command);
void WriteDat(unsigned char I2C_Data);
void OLED_Init(void);
void OLED_Setpoint(unsigned char x,unsigned char y);
void OLED_Fill(unsigned char Fill_Data);
void OLED_Clear(void);
void OLED_CLOSE(void);
void OLED_OPEN(void);
void OLED_ShowStr(unsigned char x,unsigned char y,unsigned char ch[],unsigned TextSize);
void OLED_ShowCharactor(unsigned char x,unsigned char y,unsigned char N);
void OLED_ShowPicture(unsigned char x0,unsigned char y0,unsigned char x1,unsigned char y1,unsigned char BMP[]);
#endif

综合上述所有,主要讲述了
1.stm32硬件IIC的架构以及部分寄存器的说明
2.oled屏幕原理
3.固件库 配置硬件IIC+IIC协议函数实现
4.oled驱动
代码+oled显示内容代码

基于stm32硬件IIC的oled显示相关推荐

  1. 基于STM32和ATH20实现OLED显示温湿度

    基于STM32和ATH20实现OLED显示温湿度 什么是OLED 一.主要代码 二. 硬件连接及结果 1.硬件连接 2.烧录显示 总结 参考文献 什么是OLED 有机电致发光器件(OLED)属于低电压 ...

  2. 12. STM32——硬件IIC驱动OLED屏幕显示

    STM32--硬件IIC驱动OLED屏幕显示 OLED屏幕 OLED屏幕特点 OLED屏幕接线说明 OLED屏幕显存 OLED屏幕原理 OLED屏幕常用指令 OLED屏幕字模软件的使用 写命令 写数据 ...

  3. 基于STM32移植U8g2图形库——OLED显示(HAL库)

    前言:本文主要内容为将优秀的图形库U8g2移植到STM32单片机上,用于OLED显示精美UI.其实,目前GitHub上有需要优秀的开源GUI库,但是大部分的GUI解决方案并不适合0.96 OLED(1 ...

  4. 基于STM32的0.96OLED基本显示学习,及 上下或左右的滑动显示长字符(使用硬件刷屏模式),OLED显示变量值操作详细解析

    基于STM32的0.96OLED基本显示学习,及 上下或左右的滑动显示长字符(使用硬件刷屏模式),OLED显示变量值操作详细解析 简   介 一.项目说明 二.学习入门 1)开始了解例程 三.实战过程 ...

  5. STM32硬件SPI驱动OLED

    文章目录 一.OLED相关 1.OLED简介 2.0.96寸的OLED模块概述 3.模块引脚说明 4.汉字点阵编码原理 二.硬件SPI 1.SPI简介 2.SPI的引脚映射关系 三.SPI驱动的OLE ...

  6. STM32硬件IIC的BUG问题

    问题描述 大概是这样,使用STM32硬件IIC作为主机通讯,只要不发送错误的从机地址, 通讯一直都是没问题的,因为验证程序的关系,所以在程序中修改了一下从机地址, 这时候就出现了问题,下面直接看图把 ...

  7. 利用51单片机+0.96寸iic接口oled显示图片或动图

    利用51单片机+0.96寸iic接口oled显示图片或动图 前言:之前讲过如何使用oled显示数字以及字符,但并未讲述如何显示BMP格式的图片, 这篇将在之前的基础上加以封装一些函数用来显示图片 硬件 ...

  8. 基于STM32的舱内温湿度显示设计

    基于STM32的舱内温湿度显示设计 本次设计使用正点原子的STM32F103ZET6精英开发板. 数据采集:温湿度传感器采用DHT11来采集湿度,使用DS18B20来采集温度. 显示:显示部分分为TF ...

  9. 使用STM32+硬件IIC+DMA驱动GT系列触摸屏(GT911)

    使用STM32+硬件IIC+DMA驱动GT系列触摸屏(GT911) 初始化代码 /** @brief GT911 初始化程序* @param None* @retval None*/ void GT9 ...

最新文章

  1. PHP无状态对象,(PHP)基于Token的身份验证中对无状态的理解
  2. python函数+定义+调用+多返回值+匿名函数+lambda+高级函数(reduce、map、filter)
  3. mysql binlog2sql闪回数据
  4. Cannot create a session after the response has been committed
  5. FFT字符串匹配(解决通配符问题)
  6. 百度、华为、京东、B站最新面试题汇集,实战篇
  7. Planning Strategy 和Requirement type的思考
  8. [Vue.js] 基础 -- Vue常用特性
  9. c语言lr分析器的设计与实现_[源码和文档分享]基于有限自动机的词法分析器构造...
  10. shiyou的数值分析作业
  11. Heartbeat的介绍及工作原理
  12. 用vscode编写matlab
  13. C++实现一个有理数类,包括大小比较,有理数的加减乘除。测试你的类。
  14. 一套简单实用的SQL脚本,总有你需要的
  15. APA格式参考文献引用
  16. 【读书笔记】《怪诞行为学》丹·艾瑞里
  17. 计算机网络首部检验和怎么算,计算机网络校验和算法
  18. javacv学习之实现matlab中imfill算法(孔洞填充)
  19. Science Advances|一种新型的多药物治疗使青蛙能够肢体再生
  20. 从5G到区块链,IPFS将颠覆未来!

热门文章

  1. CISSP第二章:资产安全知识点
  2. <<Java>>注释的三种方式
  3. Javaweb教程(2023-1-10)
  4. java反射 注解_Java反射中的注解
  5. 我的CSDN笔记总索引(阅读量降序,代码自动遍历生成HTML5源码)
  6. linux安装mysql提示“No package mysql-server available
  7. 【模糊综合评价的运用】——《基于模糊评价法的高校户外公共活动空间研究》论文笔记(内附MATLAB程序)
  8. Sparse R-CNN 论文精读
  9. java.lang.NullPointerException:null
  10. Tower for Mac v8.0 优秀的git客户端