目录
1.单片机:STM32F103

2.0.96寸OLED显示屏

OLED (Organic Light-Emitting Diode):有机发光二极管又称为有机电激光显示,OLED显示技术具有自发光的特性,采用薄的有机材料涂层和玻璃基板,当有电流通过时,这些有机材料就会发光,而且OLED显示屏幕可视角度大,功耗低。OLED由于同时具备自发光、不需背光源(只上电是不会亮的,驱动程序和接线正确才会点亮)、对比度高、厚度薄、视角广、反应速度快、可用于挠曲面板、使用温度范围广、结构及制程简单等优异之特性。最先接触的12864屏都是LCD的,需要背光,功耗较高,而OLED的功耗低,更加适合小系统;由于两者发光材料的不同,在不同的环境中,OLED的显示效果较佳。模块供电可以是3.3V也可以是5V,不需要修改模块电路,OLED屏具有多个控制指令,可以控制OLED的亮度、对比度、开关升压电路等指令。操作方便,功能丰富,可显示汉字、ASCII、图案等。
| 序号 | 激光测距模块 | 单片机STM32 |
| 1 | VCC | 3.3V/5V |
| 2 | SCL | PB6 |
| 3 | SDA | PB7 |
| 4 | GND | GND |
这里选用0.96寸OLED显示屏,它支持IIC通信,因此代码将以IIC展开。
整个实现过程,分为四种方式实现。
- /**************************************************/
- /* IIC Start */
- /**************************************************/
- void IIC_Start()
- {
-
- OLED_GPIO(OLED_SDA,1);
- OLED_GPIO(OLED_CLK,1);
- OLED_GPIO(OLED_SDA,0);
- OLED_GPIO(OLED_CLK,0);
- }
-
- /**************************************************/
- /* IIC Stop */
- /**************************************************/
- void IIC_Stop()
- {
- OLED_GPIO(OLED_CLK,1);
- OLED_GPIO(OLED_SDA,0);
- OLED_GPIO(OLED_CLK,1);
-
- OLED_GPIO(OLED_SDA,1);
- OLED_GPIO(OLED_CLK,1);
-
- }
-
- void IIC_Wait_Ack() //检测应答
- {
- OLED_GPIO(OLED_SDA,0);
- OLED_GPIO(OLED_CLK,1);
- OLED_GPIO(OLED_CLK,0);
-
- }
- /**************************************************/
- /* IIC Write byte */
- /**************************************************/
- void Write_IIC_Byte(uint8_t IIC_Byte)
- {
- uint8_t i;
- uint8_t m,da;
- da=IIC_Byte;
- OLED_GPIO(OLED_CLK,0);
-
- for(i=0;i<8;i++)
- {
- m=da;
- // OLED_SCLK_Clr();
- m=m&0x80;
- if(m==0x80)
- {
- OLED_GPIO(OLED_SDA,1);
- }
- else
- OLED_GPIO(OLED_SDA,0);
- da=da<<1;
- OLED_GPIO(OLED_CLK,1);
- OLED_GPIO(OLED_CLK,0);
-
- }
-
-
- }
- /*********************************************/
- /* IIC Write Command */
- /*********************************************/
- void Write_IIC_Command(uint8_t IIC_Command) //写命令
- {
- IIC_Start();
- Write_IIC_Byte(0x78); // OLED的I2C地址(禁止修改)
- IIC_Wait_Ack();
- Write_IIC_Byte(0x00); // OLED 指令(禁止修改)
- IIC_Wait_Ack();
- Write_IIC_Byte(IIC_Command);
- IIC_Wait_Ack();
- IIC_Stop();
- }
- /*********************************************/
- /* IIC Write Data */
- /*********************************************/
- void Write_IIC_Data(uint8_t IIC_Data) //写数据
- {
- IIC_Start();
- Write_IIC_Byte(0x78); // OLED的I2C地址(禁止修改)
- IIC_Wait_Ack();
- Write_IIC_Byte(0x40); // OLED 数据(禁止修改)
- IIC_Wait_Ack();
- Write_IIC_Byte(IIC_Data);
- IIC_Wait_Ack();
- IIC_Stop();
- }
- void OLED_WR_Byte(uint8_t dat,uint8_t cmd)
- {
- if(cmd)
- {
- Write_IIC_Data(dat);
- }
- else
- {
- Write_IIC_Command(dat);
- }
- }
- /**
- * @brief I2C_Configuration,初始化硬件IIC引脚
- * @param 无
- * @retval 无
- */
- void I2C_Configuration(void)
- {
- I2C_InitTypeDef I2C_InitStructure;
- GPIO_InitTypeDef GPIO_InitStructure;
-
- /*I2C1外设时钟使能 */
- OLED_I2C_CLK_INIT(OLED_I2C_CLK,ENABLE);
-
- /*I2C1外设GPIO时钟使能 */
- RCC_APB2PeriphClockCmd(OLED_I2C_SCL_GPIO_CLK | OLED_I2C_SDA_GPIO_CLK,ENABLE);
-
- /* I2C_SCL、I2C_SDA*/
- GPIO_InitStructure.GPIO_Pin = OLED_I2C_SCL_PIN;
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD; // 开漏输出
- GPIO_Init(OLED_I2C_SCL_GPIO_PORT, &GPIO_InitStructure);
-
- GPIO_InitStructure.GPIO_Pin = OLED_I2C_SDA_PIN;
- GPIO_Init(OLED_I2C_SDA_GPIO_PORT, &GPIO_InitStructure);
-
-
- /* I2C 配置 */
- I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
- I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2; /* 高电平数据稳定,低电平数据变化 SCL 时钟线的占空比 */
- I2C_InitStructure.I2C_OwnAddress1 =0x10; //主机的I2C地址.和其它设备不重复即可
- I2C_InitStructure.I2C_Ack = I2C_Ack_Enable ;
- I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; /* I2C的寻址模式 */
- I2C_InitStructure.I2C_ClockSpeed = I2C_Speed; /* 通信速率 */
-
- I2C_Init(OLED_I2C, &I2C_InitStructure); /* I2C1 初始化 */
- I2C_Cmd(OLED_I2C, ENABLE); /* 使能 I2C1 */
-
- }
-
- /**
- * @brief I2C_WriteByte,向OLED寄存器地址写一个byte的数据
- * @param addr:寄存器地址
- * data:要写入的数据
- * @retval 无
- */
- void I2C_WriteByte(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, OLED_ADDRESS, 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总线
- }
-
-
- /**
- * @brief WriteCmd,向OLED写入命令
- * @param I2C_Command:命令代码
- * @retval 无
- */
- void WriteCmd(unsigned char I2C_Command)//写命令
- {
- I2C_WriteByte(0x00, I2C_Command);
- }
-
-
- /**
- * @brief WriteDat,向OLED写入数据
- * @param I2C_Data:数据
- * @retval 无
- */
- void WriteDat(unsigned char I2C_Data)//写数据
- {
- I2C_WriteByte(0x40, I2C_Data);
- }
-
-
- /**
- * @brief OLED_Init,初始化OLED
- * @param 无
- * @retval 无
- */
- void OLED_Init(void)
- {
- delay_ms(1000); // 1s,这里的延时很重要,上电后延时,没有错误的冗余设计
-
- WriteCmd(0xAE); //display off
- WriteCmd(0x20); //Set Memory Addressing Mode
- WriteCmd(0x10); //00,Horizontal Addressing Mode;01,Vertical Addressing Mode;10,Page Addressing Mode (RESET);11,Invalid
- WriteCmd(0xb0); //Set Page Start Address for Page Addressing Mode,0-7
- WriteCmd(0xc8); //Set COM Output Scan Direction
- WriteCmd(0x00); //---set low column address
- WriteCmd(0x10); //---set high column address
- WriteCmd(0x40); //--set start line address
- WriteCmd(0x81); //--set contrast control register
- WriteCmd(0xff); //亮度调节 0x00~0xff
- WriteCmd(0xa1); //--set segment re-map 0 to 127
- WriteCmd(0xa6); //--set normal display
- WriteCmd(0xa8); //--set multiplex ratio(1 to 64)
- WriteCmd(0x3F); //
- WriteCmd(0xa4); //0xa4,Output follows RAM content;0xa5,Output ignores RAM content
- WriteCmd(0xd3); //-set display offset
- WriteCmd(0x00); //-not offset
- WriteCmd(0xd5); //--set display clock divide ratio/oscillator frequency
- WriteCmd(0xf0); //--set divide ratio
- WriteCmd(0xd9); //--set pre-charge period
- WriteCmd(0x22); //
- WriteCmd(0xda); //--set com pins hardware configuration
- WriteCmd(0x12);
- WriteCmd(0xdb); //--set vcomh
- WriteCmd(0x20); //0x20,0.77xVcc
- WriteCmd(0x8d); //--set DC-DC enable
- WriteCmd(0x14); //
- WriteCmd(0xaf); //--turn on oled panel
- }

- static void OLED_GPIO_Init(void)
- {
- GPIO_InitTypeDef GPIO_Struct;
-
- /* GPIO Ports Clock Enable */
- __HAL_RCC_GPIOB_CLK_ENABLE();
-
- GPIO_Struct.Pin = GPIO_PIN_7| GPIO_PIN_6;
- GPIO_Struct.Mode = GPIO_MODE_OUTPUT_PP;
- GPIO_Struct.Speed = GPIO_SPEED_FREQ_LOW;
- HAL_GPIO_Init(GPIOB, &GPIO_Struct);
-
- }
-
- void OLED_GPIO(uint8_t add,uint8_t date)
- {
- if(add==0)
- {
- if(date==1) HAL_GPIO_WritePin(GPIOB, GPIO_PIN_7, GPIO_PIN_SET);
- else if(date==0)HAL_GPIO_WritePin(GPIOB, GPIO_PIN_7, GPIO_PIN_RESET);
- }
- else if(add==1)
- {
- if(date==1) HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_SET);
- else if(date==0)HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_RESET);
- }
- }
- /**************************************************/
- /* IIC Start */
- /**************************************************/
- void IIC_Start()
- {
-
- OLED_GPIO(OLED_SDA,1);
- OLED_GPIO(OLED_CLK,1);
- OLED_GPIO(OLED_SDA,0);
- OLED_GPIO(OLED_CLK,0);
- }
-
- /**************************************************/
- /* IIC Stop */
- /**************************************************/
- void IIC_Stop()
- {
- OLED_GPIO(OLED_CLK,1);
- OLED_GPIO(OLED_SDA,0);
- OLED_GPIO(OLED_CLK,1);
-
- OLED_GPIO(OLED_SDA,1);
- OLED_GPIO(OLED_CLK,1);
-
- }
-
- void IIC_Wait_Ack() //检测应答
- {
- OLED_GPIO(OLED_SDA,0);
- OLED_GPIO(OLED_CLK,1);
- OLED_GPIO(OLED_CLK,0);
-
- }
- /**************************************************/
- /* IIC Write byte */
- /**************************************************/
- void Write_IIC_Byte(uint8_t IIC_Byte)
- {
- uint8_t i;
- uint8_t m,da;
- da=IIC_Byte;
- OLED_GPIO(OLED_CLK,0);
-
- for(i=0;i<8;i++)
- {
- m=da;
- // OLED_SCLK_Clr();
- m=m&0x80;
- if(m==0x80)
- {
- OLED_GPIO(OLED_SDA,1);
- }
- else
- OLED_GPIO(OLED_SDA,0);
- da=da<<1;
- OLED_GPIO(OLED_CLK,1);
- OLED_GPIO(OLED_CLK,0);
-
- }
-
-
- }
- /*********************************************/
- /* IIC Write Command */
- /*********************************************/
- void Write_IIC_Command(uint8_t IIC_Command) //写命令
- {
- IIC_Start();
- Write_IIC_Byte(0x78); // OLED的I2C地址(禁止修改)
- IIC_Wait_Ack();
- Write_IIC_Byte(0x00); // OLED 指令(禁止修改)
- IIC_Wait_Ack();
- Write_IIC_Byte(IIC_Command);
- IIC_Wait_Ack();
- IIC_Stop();
- }
- /*********************************************/
- /* IIC Write Data */
- /*********************************************/
- void Write_IIC_Data(uint8_t IIC_Data) //写数据
- {
- IIC_Start();
- Write_IIC_Byte(0x78); // OLED的I2C地址(禁止修改)
- IIC_Wait_Ack();
- Write_IIC_Byte(0x40); // OLED 数据(禁止修改)
- IIC_Wait_Ack();
- Write_IIC_Byte(IIC_Data);
- IIC_Wait_Ack();
- IIC_Stop();
- }
- void OLED_WR_Byte(uint8_t dat,uint8_t cmd)
- {
- if(cmd)
- {
- Write_IIC_Data(dat);
- }
- else
- {
- Write_IIC_Command(dat);
- }
- }

- //写命令
- void OLED_WR_CMD(uint8_t cmd)
- {
- HAL_I2C_Mem_Write(&hi2c1 ,0x78,0x00,I2C_MEMADD_SIZE_8BIT,&cmd,1,0x100);
- }
- //写数据
- void OLED_WR_DATA(uint8_t data)
- {
- HAL_I2C_Mem_Write(&hi2c1 ,0x78,0x40,I2C_MEMADD_SIZE_8BIT,&data,1,0x100);
- }
-
-
-
- void WriteCmd()
- {
- HAL_Delay(1000); // 1s,这里的延时很重要,上电后延时,没有错误的冗余设计
-
- OLED_WR_CMD(0xAE); //display off
- OLED_WR_CMD(0x20); //Set Memory Addressing Mode
- OLED_WR_CMD(0x10); //00,Horizontal Addressing Mode;01,Vertical Addressing Mode;10,Page Addressing Mode (RESET);11,Invalid
- OLED_WR_CMD(0xb0); //Set Page Start Address for Page Addressing Mode,0-7
- OLED_WR_CMD(0xc8); //Set COM Output Scan Direction
- OLED_WR_CMD(0x00); //---set low column address
- OLED_WR_CMD(0x10); //---set high column address
- OLED_WR_CMD(0x40); //--set start line address
- OLED_WR_CMD(0x81); //--set contrast control register
- OLED_WR_CMD(0xff); //亮度调节 0x00~0xff
- OLED_WR_CMD(0xa1); //--set segment re-map 0 to 127
- OLED_WR_CMD(0xa6); //--set normal display
- OLED_WR_CMD(0xa8); //--set multiplex ratio(1 to 64)
- OLED_WR_CMD(0x3F); //
- OLED_WR_CMD(0xa4); //0xa4,Output follows RAM content;0xa5,Output ignores RAM content
- OLED_WR_CMD(0xd3); //-set display offset
- OLED_WR_CMD(0x00); //-not offset
- OLED_WR_CMD(0xd5); //--set display clock divide ratio/oscillator frequency
- OLED_WR_CMD(0xf0); //--set divide ratio
- OLED_WR_CMD(0xd9); //--set pre-charge period
- OLED_WR_CMD(0x22); //
- OLED_WR_CMD(0xda); //--set com pins hardware configuration
- OLED_WR_CMD(0x12);
- OLED_WR_CMD(0xdb); //--set vcomh
- OLED_WR_CMD(0x20); //0x20,0.77xVcc
- OLED_WR_CMD(0x8d); //--set DC-DC enable
- OLED_WR_CMD(0x14); //
- OLED_WR_CMD(0xaf); //--turn on oled panel
- }


由于频闪的原因,拍不全。
从代码上可以发现,IIC实现比模拟IIC实现起来要简单不少。
创作不易,下面提供下载链接,涉及以上四种实现方法源码。
如有问题或需求可私信交流
源码下载地址: