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

news/2024/6/3 17:34:33 标签: 单片机, stm32, 嵌入式硬件

一、简介

使用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.niftyadmin.cn/n/463947.html

相关文章

UDP 广播/组播

广播UDP与单播UDP的区别就是IP地址不同&#xff0c;广播使用广播地址xxx.xxx.xxx.255&#xff0c;将消息发送到在同一广播网络上的每个主机&#xff0c;广播/组播只能用udp进行实现 函数:int setsockopt(int sockfd, int level, int optname, const void *optval, socklen_topt…

DevOps系列文章之 linux安装ftp

第一步 1、用root 进入系统 2、使用命令 rpm -qa|grep vsftpd 查看系统是否安装了ftp&#xff0c;若安装了vsftp&#xff0c;使用这个命令会在屏幕上显示vsftpd的版本 3、使用命令rpm -e vsftpd 即可卸载ftp 4、再使用rpm -qa|grep vsftpd 查看系统是否已删除ftp&#xff0…

day23 | 669. 修剪二叉搜索树、108.将有序数组转换为二叉搜索树、538.把二叉搜索树转换为累加树

目录&#xff1a; 解题及思路学习 669. 修剪二叉搜索树 链接&#xff1a;https://leetcode.cn/problems/trim-a-binary-search-tree/ 给你二叉搜索树的根节点 root &#xff0c;同时给定最小边界low 和最大边界 high。通过修剪二叉搜索树&#xff0c;使得所有节点的值在[lo…

易混淆单词总结

英文中文frustrationn. 挫败&#xff0c;沮丧frustratevt. 挫败&#xff0c;使沮丧&#xff0c;阻止&#xff0c;挫败frustrated adj. 沮丧的 v. frustrate的过去和过分 frustrating adj. 令人沮丧的 v. frustrate的现分 infrastructuren. 基础设施infrastructuraladj. 基础设施…

Godot 4 源码分析 - 练手 - 和谐共生

今天看到一个微信视频&#xff0c;和谐共生&#xff0c;大概效果如下 https://live.csdn.net/v/306826 研究这么长时间的Godot&#xff0c;今天试试能否实现上述效果 粗看一下&#xff0c;这个效果实现分几步&#xff1a; 1. 画圆&#xff0c;并确定多个圆的位置规律 2. 动…

Nginx 的学习与实战【二】

三、配置文件 nginx.conf 配置文件&#xff1a; user nginx; worker_processes auto;error_log /var/log/nginx/error.log notice; pid /var/run/nginx.pid;events {worker_connections 1024; }http {include /etc/nginx/mime.types;default_type applicat…

你不知道的HTML属性,让你的网页更加响应式

前言 当我们谈论 HTML 时&#xff0c;通常会想到一些常见的属性&#xff0c;如 class、id、href 等等。但是&#xff0c;HTML 还有许多你可能从未听说过的属性&#xff0c;这些属性可以让你的网页更加丰富多彩。在本文中&#xff0c;我将介绍一些你可能不知道的 HTML 属性&…

ModuleNotFoundError: No module named “pbxproj“

项目中有个打包脚本需要用到pbxproj这个python库&#xff0c;这里也正常通过pip安装了pbxproj&#xff0c;但是实际上执行脚本的时候报了 ModuleNotFoundError: No module named pbxproj 那么出现这个问题第一反应是环境变量添加错了&#xff0c;于是打开自己的.zshrc文件&am…