智能小车使用IIC屏幕做动作显示界面

news2024/11/20 1:34:57

一、简介

使用0.96寸IIC屏幕作为遥控动作的显示界面。

外设引脚

 stm32f103c8t6单片机IIC引脚有两组

 

 使用I2C1,对应的时钟与数据线分别为PB6、PB7。

IIC屏幕指令

//	OLED_WR_Byte(0xAE,OLED_CMD);//--turn off oled panel
//	OLED_WR_Byte(0x00,OLED_CMD);//---set low column address
//	OLED_WR_Byte(0x10,OLED_CMD);//---set high column address
//	OLED_WR_Byte(0x40,OLED_CMD);//--set start line address  Set Mapping RAM Display Start Line (0x00~0x3F)
//	OLED_WR_Byte(0x81,OLED_CMD);//--set contrast control register
//	OLED_WR_Byte(0xCF,OLED_CMD);// Set SEG Output Current Brightness
//	OLED_WR_Byte(0xA1,OLED_CMD);//--Set SEG/Column Mapping     0xa0左右反置 0xa1正常
//	OLED_WR_Byte(0xC8,OLED_CMD);//Set COM/Row Scan Direction   0xc0上下反置 0xc8正常
//	OLED_WR_Byte(0xA6,OLED_CMD);//--set normal display
//	OLED_WR_Byte(0xA8,OLED_CMD);//--set multiplex ratio(1 to 64)
//	OLED_WR_Byte(0x3f,OLED_CMD);//--1/64 duty
//	OLED_WR_Byte(0xD3,OLED_CMD);//-set display offset	Shift Mapping RAM Counter (0x00~0x3F)
//	OLED_WR_Byte(0x00,OLED_CMD);//-not offset
//	OLED_WR_Byte(0xd5,OLED_CMD);//--set display clock divide ratio/oscillator frequency
//	OLED_WR_Byte(0x80,OLED_CMD);//--set divide ratio, Set Clock as 100 Frames/Sec
//	OLED_WR_Byte(0xD9,OLED_CMD);//--set pre-charge period
//	OLED_WR_Byte(0xF1,OLED_CMD);//Set Pre-Charge as 15 Clocks & Discharge as 1 Clock
//	OLED_WR_Byte(0xDA,OLED_CMD);//--set com pins hardware configuration
//	OLED_WR_Byte(0x12,OLED_CMD);
//	OLED_WR_Byte(0xDB,OLED_CMD);//--set vcomh
//	OLED_WR_Byte(0x30,OLED_CMD);//Set VCOM Deselect Level
//	OLED_WR_Byte(0x20,OLED_CMD);//-Set Page Addressing Mode (0x00/0x01/0x02)
//	OLED_WR_Byte(0x02,OLED_CMD);//
//	OLED_WR_Byte(0x8D,OLED_CMD);//--set Charge Pump enable/disable
//	OLED_WR_Byte(0x14,OLED_CMD);//--set(0x10) disable
	
	I2C_ByteWrite(0xAE,OLED_CMD); //关闭显示
	I2C_ByteWrite(0xD5,OLED_CMD); //设置时钟分频因子,震荡频率
	I2C_ByteWrite(0x80,OLED_CMD);   //[3:0],分频因子;[7:4],震荡频率
	I2C_ByteWrite(0xA8,OLED_CMD); //设置驱动路数
	I2C_ByteWrite(0X3F,OLED_CMD); //默认0X3F(1/64) 
	I2C_ByteWrite(0xD3,OLED_CMD); //设置显示偏移
	I2C_ByteWrite(0X00,OLED_CMD); //默认为0

	I2C_ByteWrite(0x40,OLED_CMD); //设置显示开始行 [5:0],行数.
													    
	I2C_ByteWrite(0x8D,OLED_CMD); //电荷泵设置
	I2C_ByteWrite(0x14,OLED_CMD); //bit2,开启/关闭
	I2C_ByteWrite(0x20,OLED_CMD); //设置内存地址模式
	I2C_ByteWrite(0x02,OLED_CMD); //[1:0],00,列地址模式;01,行地址模式;10,页地址模式;默认10;
	I2C_ByteWrite(0xA1,OLED_CMD); //段重定义设置,bit0:0,0->0;1,0->127;
	I2C_ByteWrite(0xC0,OLED_CMD); //设置COM扫描方向;bit3:0,普通模式;1,重定义模式 COM[N-1]->COM0;N:驱动路数
	I2C_ByteWrite(0xDA,OLED_CMD); //设置COM硬件引脚配置
	I2C_ByteWrite(0x12,OLED_CMD); //[5:4]配置
		 
	I2C_ByteWrite(0x81,OLED_CMD); //对比度设置
	I2C_ByteWrite(0xEF,OLED_CMD); //1~255;默认0X7F (亮度设置,越大越亮)
	I2C_ByteWrite(0xD9,OLED_CMD); //设置预充电周期
	I2C_ByteWrite(0xf1,OLED_CMD); //[3:0],PHASE 1;[7:4],PHASE 2;
	I2C_ByteWrite(0xDB,OLED_CMD); //设置VCOMH 电压倍率
	I2C_ByteWrite(0x30,OLED_CMD); //[6:4] 000,0.65*vcc;001,0.77*vcc;011,0.83*vcc;

	I2C_ByteWrite(0xA4,OLED_CMD); //全局显示开启;bit0:1,开启;0,关闭;(白屏/黑屏)
	I2C_ByteWrite(0xA6,OLED_CMD); //设置显示方式;bit0:1,反相显示;0,正常显示	    						   
	I2C_ByteWrite(0xAF,OLED_CMD); //开启显示

二、编码

2.1、IIC协议与IO口模拟IIC

协议内容

//起始信号
void I2C_Start(void)
{
	OLED_SDA_Set();
	OLED_SCL_Set();
	IIC_delay();
	OLED_SDA_Clr();
	IIC_delay();
	OLED_SCL_Clr();
	IIC_delay();
}

结束信号
void I2C_Stop(void)
{
	OLED_SDA_Clr();
	OLED_SCL_Set();
	IIC_delay();
	OLED_SDA_Set();
}

等待信号响应
void I2C_WaitAck(void) //测数据信号的电平
{
	OLED_SDA_Set();
	IIC_delay();
	OLED_SCL_Set();
	IIC_delay();
	OLED_SCL_Clr();
	IIC_delay();
}

写入一个字节
void Send_Byte(u8 dat)
{
	u8 i;
	for(i=0;i<8;i++)
	{
		if(dat&0x80)//将dat的8位从最高位依次写入
		{
			OLED_SDA_Set();
    }
		else
		{
			OLED_SDA_Clr();
    }
		IIC_delay();
		OLED_SCL_Set();
		IIC_delay();
		OLED_SCL_Clr();//将时钟信号设置为低电平
		dat<<=1;
  }
}

发送一个字节
mode:数据/命令标志 0,表示命令;1,表示数据;
void OLED_WR_Byte(u8 dat,u8 mode)
{
	I2C_Start();
	Send_Byte(0x78);
	I2C_WaitAck();
	if(mode){Send_Byte(0x40);}
  else{Send_Byte(0x00);}
	I2C_WaitAck();
	Send_Byte(dat);
	I2C_WaitAck();
	I2C_Stop();
}

2.2、库函数配置

2.2.1、IIC库函数配置

GPIO_InitTypeDef  GPIO_InitStructure;
	I2C_InitTypeDef I2C_InitStructure; 
	
 	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);	
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1,ENABLE);
	
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;	 
 	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD; 		 
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
 	GPIO_Init(GPIOB, &GPIO_InitStructure);	 
 	//GPIO_SetBits(GPIOB,GPIO_Pin_6|GPIO_Pin_7);
	
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;	
	GPIO_Init(GPIOB, &GPIO_InitStructure);	 
	
	/* I2C 配置 */
  I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;	
  I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;	/* 高电平数据稳定,低电平数据变化 SCL 时钟线的占空比 */
  I2C_InitStructure.I2C_OwnAddress1 =0x78;    //主机的I2C地址
  I2C_InitStructure.I2C_Ack = I2C_Ack_Enable ;	
  I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;	/* I2C的寻址模式 */
  I2C_InitStructure.I2C_ClockSpeed = 400000;	                     /* 通信速率 */
  
  I2C_Init(I2C1, &I2C_InitStructure);	                        /* I2C1 初始化 */
	I2C_Cmd(I2C1, ENABLE);  

2.2.2、向IIC外设写数据库函数配置

void I2C_ByteWrite(uint8_t addr,uint8_t data) 
{
 while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY));
	
	I2C_GenerateSTART(I2C1, ENABLE);//开启I2C1
	while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));/*EV5,主模式*/

	I2C_Send7bitAddress(I2C1, 0x78, I2C_Direction_Transmitter);//器件地址 -- 默认0x78
	while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));

	I2C_SendData(I2C1, addr);//寄存器地址
	while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));

	I2C_SendData(I2C1, data);//发送数据
	while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
	
	I2C_GenerateSTOP(I2C1, ENABLE);//关闭I2C1总线
}

2.2.3、写指令与写数据

void WriteCmd(unsigned char I2C_Commangd)
{
   I2C_ByteWrite(0x00,I2C_Commangd);
}


void WriteData(unsigned char I2C_Data) //  写数据
{
    I2C_ByteWrite(0x40,I2C_Data); 
}

void WriteByte(unsigned char mode,unsigned char I2C_Operation)
{
  if(mode==0x01)
  {
     I2C_ByteWrite(0x40,I2C_Operation); 
  }
  else
  {
   I2C_ByteWrite(0x00,I2C_Operation);
  }
}

2.2.4、从设备向从IIC总线读数据

uint8_t I2C_ByteRead(uint8_t REG_Address) //从IIC设备寄存器中读取一个字节
{
	uint8_t REG_data;	
	while(I2C_GetFlagStatus(I2C1,I2C_FLAG_BUSY));	
	I2C_GenerateSTART(I2C1,ENABLE);//起始信号	
	
	while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_MODE_SELECT));	
	I2C_Send7bitAddress(I2C1,SlaveAddress,I2C_Direction_Transmitter);//发送设备地址+写信号	
	
	while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));//	
	I2C_Cmd(I2C1,ENABLE);	
	I2C_SendData(I2C1,REG_Address);//发送存储单元地址,从0开始	
	
	while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTED));	
	I2C_GenerateSTART(I2C1,ENABLE);//起始信号	
	
	while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_MODE_SELECT));	
	I2C_Send7bitAddress(I2C1,SlaveAddress,I2C_Direction_Receiver);//发送设备地址+读信号	
	
	while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));	
	I2C_AcknowledgeConfig(I2C1,DISABLE);	
	I2C_GenerateSTOP(I2C1,ENABLE);	
	
	while(!(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_RECEIVED)));	
	REG_data=I2C_ReceiveData(I2C1);//读出寄存器数据	
	
	return REG_data;
}

2.2.5、OLED指令初始化

//OLED的初始化
void OLED_Init(void)
{
	delay_ms(1000);

	WriteCmd(0xAE); //关闭显示
	WriteCmd(0xD5); //设置时钟分频因子,震荡频率
	WriteCmd(0x80);   //[3:0],分频因子;[7:4],震荡频率
	WriteCmd(0xA8); //设置驱动路数
	WriteCmd(0X3F); //默认0X3F(1/64) 
	WriteCmd(0xD3); //设置显示偏移
	WriteCmd(0X00); //默认为0

	WriteCmd(0x40); //设置显示开始行 [5:0],行数.
													    
	WriteCmd(0x8D); //电荷泵设置
	WriteCmd(0x14); //bit2,开启/关闭
	WriteCmd(0x20); //设置内存地址模式
	WriteCmd(0x02); //[1:0],00,列地址模式;01,行地址模式;10,页地址模式;默认10;
	WriteCmd(0xA1); //段重定义设置,bit0:0,0->0;1,0->127;
	WriteCmd(0xC0); //设置COM扫描方向;bit3:0,普通模式;1,重定义模式 COM[N-1]->COM0;N:驱动路数
	WriteCmd(0xDA); //设置COM硬件引脚配置
	WriteCmd(0x12); //[5:4]配置
		 
	WriteCmd(0x81); //对比度设置
	WriteCmd(0xEF); //1~255;默认0X7F (亮度设置,越大越亮)
	WriteCmd(0xD9); //设置预充电周期
	WriteCmd(0xf1); //[3:0],PHASE 1;[7:4],PHASE 2;
	WriteCmd(0xDB); //设置VCOMH 电压倍率
	WriteCmd(0x30); //[6:4] 000,0.65*vcc;001,0.77*vcc;011,0.83*vcc;

	WriteCmd(0xA4); //全局显示开启;bit0:1,开启;0,关闭;(白屏/黑屏)
	WriteCmd(0xA6); //设置显示方式;bit0:1,反相显示;0,正常显示	    						   
	WriteCmd(0xAF); //开启显示	
	
}

2.3、OLED屏幕编码

 

OLED的ARM,每一行为一页,每一页有128个字节(8行128列即8*128bit 高电平熄灭,低电平点亮),共8页。 

页寻址:在页寻址模式下,读/写显示RAM后,列地址指针自动增加1。如果列地址指针到达列结束地址。列地址指针复位,用户重新设置行地址指针,以便访问新页。

设置坐标

  1. 通过命令(B0h-B7h)设置目标显示位置页起始地址
  2. 通过命令(00h-0Fh)设置列起始地址低位
  3. 通过命令(10h-1Fh)设置列起始地址高位
void OLED_SetPos(unsigned char x, unsigned char y) 
{ 
	WriteCmd(0xb0+y);//0xb0起始地址 1011 0000  // x[0~7]行  y[0~127]列
	WriteCmd(((x&0xf0)>>4)|0x10);// 第四位 0001 1111  设置高位
	WriteCmd((x&0x0f)|0x01);     // 第0位  0000 0001  设置低位
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/680846.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

07- c语言指针 (C语言)

一 指针的引入 1、一般把内存中的一个字节称为一个内存单元。 2、为了正确地访问这些内存单元&#xff0c;必须为每个内存单元编上号。根据一个内存单元的编号即可准确地找到该内存单元。内存单元的编号也叫做地址&#xff0c;通常也把这个地址称为指针。 3、如果在程序中定义…

车载网络测试 - CANCANFD - 基础篇_03

十、发送方式与过滤方式 1、广播发送及规则 我们以小组讨论现场为例来说明CAN总线广播发送规则&#xff1a; 1&#xff09;一个房间代表同一路CAN总线&#xff0c;每一个小组代表一个CAN Node&#xff0c;每一个小组成员发言代表发送一帧CAN报文&#xff0c;对所有的小组成员进…

生成对抗网络

1 GAN基本概念 1.1 GAN介绍 GAN的英文全称是Generative Adversarial Network&#xff0c;中文名是生成对抗网络。它由两个部分组成&#xff0c;生成器和鉴别器&#xff08;又称判别器&#xff09;&#xff0c;生成网络&#xff08;Generator&#xff09;负责生成模拟数据&…

【Python】异常处理 ④ ( 异常处理 else 语句 | 异常处理 finally 语句 )

文章目录 一、Python 异常捕获 else 语句1、异常捕获 else 语句2、代码示例 - 没有触发 else 语句的情况3、代码示例 - 触发 else 语句的情况 二、Python 异常捕获 finally 语句1、异常捕获 finally 语句2、代码示例 - 出现异常后执行 finally 语句 一、Python 异常捕获 else 语…

展示和标注图像:探索Gradio AnnotatedImage模块的功能

❤️觉得内容不错的话&#xff0c;欢迎点赞收藏加关注&#x1f60a;&#x1f60a;&#x1f60a;&#xff0c;后续会继续输入更多优质内容❤️ &#x1f449;有问题欢迎大家加关注私戳或者评论&#xff08;包括但不限于NLP算法相关&#xff0c;linux学习相关&#xff0c;读研读博…

代码生成器原理分析

代码生成器原理分析 理解代码生成器的需求和实现思路掌握freemaker的使用 理解数据库中的元数据完成环境搭建工作 浅谈代码生成器 概述 在项目开发过程中&#xff0c;关注点更多是在业务功能的开发及保证业务流程的正确性上&#xff0c;对于重复性的代码编写占据了程 序员…

指标综合评价(定性指标定量化、指标正相关化、赋权重)

目录 一、定性指标定量化 二、将指标同型化 线性比例变换法 极差变换法 二、评价指标赋予权重 三、综合评价 战斗机性能的综合评价问题 例&#xff1a;战斗机的性能指标主要包括最大速度、飞行半径、最大负载、隐身性能、垂直起降性能、可靠性、灵敏度等指标和相关费用。…

Vue+Element UI 生鲜管理系统简介及项目搭建,页面布局(一)

文章目录 浅谈一、背景二、搭建创建vue项目vue项目结构简介安装Element UI库安装axios安装querystring安装normalize.css安装echarts运行删除无用组件基础css样式导入 三、页面布局配置路由布局flex布局&#xff08;弹性盒子&#xff09;固定布局固定布局配置路由 浅谈 自从入…

【Rust】2、实战:文件、网络、时间、进程-线程-容器、内核、信号-中断-异常

文章目录 七、文件和存储7.2 serde 与 bincode 序列化7.3 实现一个 hexdump7.4 操作文件7.4.1 打开文件7.4.2 用 std::fs::Path 交互 7.5 基于 append 模式实现 kv数据库7.5.1 kv 模型7.5.2 命令行接口 7.6 前端代码7.6.1 用条件编译定制要编译的内容 7.7 核心&#xff1a;LIBA…

【Java高级语法】(十五)lambda表达式:给你一颗语法糖Lambda,解析函数式编程的杰作~

Java高级语法详解之lambda表达式 1️⃣ 概念2️⃣ 优势和缺点3️⃣ 使用3.1 语法结构3.2 案例3.2.1 无参Lambda3.2.2 带有一个参数3.2.3 带有多个参数3.2.4 方法引用的简化形式 4️⃣ 应用场景5️⃣ 优化技巧6️⃣ 原理7️⃣ 注意性能问题&#x1f33e; 总结 1️⃣ 概念 Java …

架构设计第十一讲:架构之高并发:限流

架构设计第十一讲&#xff1a;架构之高并发&#xff1a;限流 每个系统都有服务的上线&#xff0c;所以当流量超过服务极限能力时&#xff0c;系统可能会出现卡死、崩溃的情况&#xff0c;所以就有了降级和限流。限流其实就是&#xff1a;当高并发或者瞬时高并发时&#xff0c;为…

rabbitmq第三课-RabbitMQ高级功能详解以及常用插件实战

一、选择合适的队列. 实际上是可以选择三种队列类型的&#xff0c;classic经典队列&#xff0c;Quorum仲裁队列&#xff0c;Stream流式队列。 后面这两种队列也是RabbitMQ在最近的几个大的版本中推出的新的队列类型。3.8.x推出了Quorum仲裁队列&#xff0c;3.9.x推出了Stream流…

MyBatis何时使用一级缓存,何时使用二级缓存?

Mybatis设计2级缓存来提升数据检索效率&#xff0c;避免每次都查询数据库。 一、一级缓存 一级缓存 Mybatis 的一级缓存是指 SQLSession&#xff0c;一级缓存的作用域是 SQlSession , Mabits 默认开启一级缓存。 在同一个SqlSession中&#xff0c;执行相同的SQL查询时&#x…

基于STM32CUBEMX驱动TOF模块VL6180与VL6180X(2)----修改测量范围

概述 当使用VL6180传感器进行测距时&#xff0c;可以通过修改缩放因子来改变可测量的距离范围。VL6180是一种基于飞行时间原理的传感器&#xff0c;通过测量光信号的往返时间来确定物体与传感器之间的距离。 默认情况下&#xff0c;VL6180传感器的测距范围约为0至200毫米。然…

显卡检测工具:GPU-Z

今天小编为大家测试了一款轻量级的GPU显卡的测试工具&#xff0c;可以查看GPU的详细信息&#xff0c;以供各位同学们学习。 一、简单介绍 GPU-Z是一款方便实用的软件工具&#xff0c;专门为用户提供视频卡和GPU的详尽信息。它具有轻巧的特点&#xff0c;不需要安装即可使用&am…

2023版智慧高速智慧公路总体建设方案,售前人员必备方案

导读&#xff1a;原文《智慧高速智慧公路总体建设方案》共83页PPT&#xff08;获取来源见文尾&#xff09;&#xff0c;本文精选其中精华及架构部分&#xff0c;逻辑清晰、内容完整&#xff0c;为快速形成售前方案提供参考。 如需获取完整的电子版内容参考学习 您可以关注评论…

【雷达原理】基本雷达方程的推导

基本雷达方程 一、研究目的二、推导过程1、基本雷达方程常用的表达形式2、计算案例3、仿真代码 参考文献 一、研究目的 雷达方程定量地描述了作用距离与雷达参数及目标特性之间的关系。 研究雷达方程主要有以下作用&#xff1a; &#xff08;1&#xff09;根据雷达参数来估算雷…

慕课:笔记

课程链接&#xff1a;直面JavaScript中的30个疑难杂症_JavaScript面试题-慕课网 第二章&#xff1a;数据类型 数据类型是每门编程语言的必修之课&#xff0c;你是否对JavaScript的数据类型和检测存在困惑&#xff0c;本章节将为你揭晓其中的奥秘&#xff0c;让你对数据类型有…

矩阵压缩算法

当矩阵中存在着重复元素时&#xff0c;为了节省空间会采用压缩算法&#xff0c;关键在于原矩阵空间与压缩后数据结构的对应&#xff1b; 1.对称压缩&#xff1a;数据沿对角线对称的情况&#xff1b; 将矩阵压缩为一维数组&#xff0c;数组的长度是&#xff1a; 对于num[n][n…

VMware虚拟机暴露端口至公网方法流程详解

目录 需求背景 解决方法 准备工作 虚拟机ip设置方法 需求背景 一台电脑需要连接另一台电脑上的虚拟机的端口&#xff0c;直接ping是无法ping通的&#xff0c;因为本地虚拟机的端口未暴露至公网。 解决方法 虚拟机&#xff1a;CentOS 7 64 Linux 本机&#xff1a;Window…