文章目录
- 一、功能简介
- 二、软件设计
- 三、实验现象
- 联系作者
一、功能简介
本项目使用STM32F103C8T6单片机控制器,使IIC OLED液晶等。
主要功能:
系统运行后,OLED显示动画界面。
二、软件设计
/*
作者:嗨小易(QQ:3443792007)*/void IIC_GPIO_Config(void)
{GPIO_InitTypeDef GPIO_InitStructure;RCC_APB2PeriphClockCmd(OLED_SCL_RCC|OLED_SDA_RCC, ENABLE); /* 打开GPIO时钟 */GPIO_InitStructure.GPIO_Pin = OLED_SCL_PIN;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD; //开漏输出GPIO_Init(OLED_SCL_GPIO_PORT, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin = OLED_SDA_PIN;GPIO_Init(OLED_SDA_GPIO_PORT, &GPIO_InitStructure);//给一个停止信号, 复位IIC总线上的所有设备到待机模式IIC_Stop();
}//初始化SSD1306
void OLED_Init(void)
{HZ=GB16_NUM();delay_ms(100);IIC_GPIO_Config();Write_IIC_Command(0xAE); //--display offWrite_IIC_Command(0x00); //---set low column addressWrite_IIC_Command(0x10); //---set high column addressWrite_IIC_Command(0x40); //--set start line addressWrite_IIC_Command(0xB0); //--set page addressWrite_IIC_Command(0x81); // contract controlWrite_IIC_Command(0xFF); //--128Write_IIC_Command(0xA1); //set segment remapWrite_IIC_Command(0xA6); //--normal / reverseWrite_IIC_Command(0xA8); //--set multiplex ratio(1 to 64)Write_IIC_Command(0x3F); //--1/32 dutyWrite_IIC_Command(0xC8); //Com scan directionWrite_IIC_Command(0xD3); //-set display offsetWrite_IIC_Command(0x00); //Write_IIC_Command(0xD5); //set osc divisionWrite_IIC_Command(0x80); //Write_IIC_Command(0xD8); //set area color mode offWrite_IIC_Command(0x05); //Write_IIC_Command(0xD9); //Set Pre-Charge PeriodWrite_IIC_Command(0xF1); //Write_IIC_Command(0xDA); //set com pin configuartionWrite_IIC_Command(0x12); //Write_IIC_Command(0xDB); //set VcomhWrite_IIC_Command(0x30); //Write_IIC_Command(0x8D); //set charge pump enableWrite_IIC_Command(0x14); //Write_IIC_Command(0xAF); //--turn on oled panel
}static void IIC_Delay(void)
{uint8_t i=3;while(i--);
}/**************************************************
* 函 数 名: IIC_Start
* 功能说明: CPU发起IIC总线启动信号
* 形 参:无
* 返 回 值: 无
***************************************************/
void IIC_Start(void)
{/* 当SCL高电平时,SDA出现一个下跳沿表示IIC总线启动信号 */OLED_SDA=1;OLED_SCL=1;IIC_Delay();OLED_SDA=0;IIC_Delay();OLED_SCL=0;IIC_Delay();
}/*************************************************
* 函 数 名: IIC_Stop
* 功能说明: CPU发起IIC总线停止信号
* 形 参:无
* 返 回 值: 无
*************************************************/
void IIC_Stop(void)
{/* 当SCL高电平时,SDA出现一个上跳沿表示IIC总线停止信号 */OLED_SDA=0;OLED_SCL=1;IIC_Delay();OLED_SDA=1;
}/***************************************************************************
* 函 数 名: IIC_WaitAck
* 功能说明: CPU产生一个时钟,并读取器件的ACK应答信号
* 形 参:无
* 返 回 值: 返回0表示正确应答,1表示无器件响应
****************************************************************************/
//uint8_t IIC_WaitAck(void)
void IIC_WaitAck(void)
{OLED_SDA=1; /* CPU释放SDA总线 */IIC_Delay();OLED_SCL=1; /* CPU驱动SCL = 1, 此时器件会返回ACK应答 */IIC_Delay();OLED_SCL=0;IIC_Delay();
}//向IIC总线写数据
void Write_IIC_Byte(uint8_t _ucByte)
{uint8_t i;/* 先发送字节的高位bit7 */for (i = 0; i < 8; i++){ if (_ucByte & 0x80){OLED_SDA=1;}else{OLED_SDA=0;}IIC_Delay();OLED_SCL=1;IIC_Delay(); OLED_SCL=0;_ucByte <<= 1; /* 左移一个bit */}
}//写命令
void Write_IIC_Command(u8 IIC_Command)
{IIC_Start();Write_IIC_Byte(OLED_ADDRESS);//OLED地址IIC_WaitAck();Write_IIC_Byte(0x00);//寄存器地址IIC_WaitAck();Write_IIC_Byte(IIC_Command);IIC_WaitAck();IIC_Stop();
}//写数据
void Write_IIC_Data(u8 IIC_Data)
{IIC_Start();Write_IIC_Byte(OLED_ADDRESS);//OLED地址IIC_WaitAck();Write_IIC_Byte(0x40);//寄存器地址IIC_WaitAck();Write_IIC_Byte(IIC_Data);IIC_WaitAck();IIC_Stop();
}//将OLED从休眠中唤醒
void OLED_ON(void)
{Write_IIC_Command(0X8D); //设置电荷泵Write_IIC_Command(0X14); //开启电荷泵Write_IIC_Command(0XAF); //OLED唤醒
}//让OLED休眠 -- 休眠模式下,OLED功耗不到10uA
void OLED_OFF(void)
{Write_IIC_Command(0X8D); //设置电荷泵Write_IIC_Command(0X10); //关闭电荷泵Write_IIC_Command(0XAE); //OLED休眠
}//OLED全屏填充
void OLED_Fill(u8 fill_Data)
{u8 m,n;for(m=0;m<8;m++){Write_IIC_Command(0xb0+m); //page0-page1Write_IIC_Command(0x00); //low column start addressWrite_IIC_Command(0x10); //high column start addressfor(n=0;n<130;n++){Write_IIC_Data(fill_Data);}}
}//设置起始点坐标
void OLED_Set_Pos(u8 x, u8 y)
{ Write_IIC_Command(0xb0+y);Write_IIC_Command((((x+2)&0xf0)>>4)|0x10);Write_IIC_Command(((x+2)&0x0f)|0x01);
}//更新显存到OLED
void OLED_Refresh(void)
{u8 i,n;for(i=0;i<8;i++){Write_IIC_Command(0xb0+i); //设置行起始地址Write_IIC_Command(0x00); //设置低列起始地址Write_IIC_Command(0x10); //设置高列起始地址IIC_Start();Write_IIC_Byte(0x78);IIC_WaitAck();Write_IIC_Byte(0x40);IIC_WaitAck();for(n=0;n<130;n++){Write_IIC_Byte(OLED_GRAM[n][i]);IIC_WaitAck();}IIC_Stop();}
}//清屏
void OLED_Clear(void)
{OLED_Fill(0x00);
}//在指定位置显示一个字符,包括部分字符
//x:0~127
//y:0~63
void OLED_ShowChar(u8 x, u8 y, u8 chr)
{u8 c = 0, i = 0;c = chr - ' '; //得到偏移后的值if(x > 130 - 1){x = 0;y = y + 2;}OLED_Set_Pos(x, y);for(i = 0; i < 8; i++)Write_IIC_Data(zf[c * 16 + i]);OLED_Set_Pos(x, y + 1);for(i = 0; i < 8; i++)Write_IIC_Data(zf[c * 16 + i + 8]);
}
//m^n函数
u32 oled_pow(u8 m, u8 n)
{u32 result = 1;while(n--)result *= m;return result;
}
//显示个数字
//x,y :起点坐标
//len :数字的位数
//num:数值(0~4294967295);
//mode: 为1:显示0 为0:显示空格
void OLED_ShowNum(u8 x, u8 y, u32 num, u8 len,u8 mode)
{u8 t, temp;u8 enshow=0;for(t = 0; t < len; t++){temp = (num / oled_pow(10, len - t - 1)) % 10;if(enshow==0&&t<(len-1)){if(temp==0){if(mode)OLED_ShowChar(x + 8*t, y, '0');elseOLED_ShowChar(x + 8*t, y, ' ');continue;}else enshow=1; }OLED_ShowChar(x + 8*t, y, temp + '0');}
}//显示中英文字符
void OLED_ShowCH(u8 x, u8 y,u8 *chs)
{u32 i=0;u32 j;char* m;while (*chs != '\0'){if (*chs > 0xa0) //汉字内码都是大于0xa0{for (i=0 ;i < HZ;i++){ if(x>112){x=0;y=y+2;}if ((*chs == hz_index[i*2]) && (*(chs+1) == hz_index[i*2+1])){OLED_Set_Pos(x, y);for(j=0;j<16;j++)Write_IIC_Data(hz[i*32+j]);OLED_Set_Pos(x,y+1);for(j=0;j<16;j++)Write_IIC_Data(hz[i*32+j+16]);x +=16;break;}}chs+=2;}else{if(x>122){x=0;y=y+2;}m=strchr(zf_index,*chs);if (m!=NULL){OLED_Set_Pos(x, y);for(j = 0; j < 8; j++)Write_IIC_Data(zf[((u8)*m-' ') * 16 + j]);OLED_Set_Pos(x, y + 1);for(j = 0; j < 8; j++)Write_IIC_Data(zf[((u8)*m-' ') * 16 + j + 8]);x += 8;}chs++;}}
}// x0,y0 -- 起始点坐标(x0:0~127, y0:0~7); x1,y1 -- 起点对角线(结束点)的坐标(x1:1~128,y1:1~8)
void OLED_DrawBMP(u8 x0,u8 y0,u8 x1,u8 y1,u8 BMP[])
{u16 j=0;u8 x,y;if(y1%8==0)y = y1/8;elsey = y1/8 + 1;for(y=y0;y<y1;y++){OLED_Set_Pos(x0,y);for(x=x0;x<x1;x++){Write_IIC_Data(BMP[j++]);}}
}//清除最后两行文字
void ShowTrashNoPeople(void)
{u8 m,n; //m起始行数for(m=0;m<8;m++){Write_IIC_Command(0xb0+m); //page0-page1Write_IIC_Command(0x00); //low column start addressWrite_IIC_Command(0x10); //high column start addressfor(n=0;n<130;n++){Write_IIC_Data(0x00);}}
}
三、实验现象
B站演示视频:https://space.bilibili.com/444388619
联系作者
专注于51单片机、STM32、国产32、DSP、Proteus、ardunio、ESP32、物联网软件开发,PCB设计,视频分享,技术交流。