stm32驱动ssd1306配置_STM32 OLED 屏幕 驱动芯片SSD1306 IIC代码

#include "oled.h"

#include "stdlib.h"

#include "oledfont.h"

#include "delay.h"

#include "usart.h"

//SSD1306 OLED 驱动IC驱动代码

//驱动方式:IIC

//OLED的显存

//存放格式如下.

//[0]0 1 2 3 ... 127

//[1]0 1 2 3 ... 127

//[2]0 1 2 3 ... 127

//[3]0 1 2 3 ... 127

//[4]0 1 2 3 ... 127

//[5]0 1 2 3 ... 127

//[6]0 1 2 3 ... 127

//[7]0 1 2 3 ... 127

u8 OLED_GRAM[128][8];

//更新显存到LCD

void OLED_Refresh_Gram(void)

{

u8 i,n;

for(i=0;i<8;i++)

{

OLED_WR_Byte (0xb0+i,OLED_CMD);    //设置页地址(0~7)

OLED_WR_Byte (0x00,OLED_CMD);      //设置显示位置—列低地址

OLED_WR_Byte (0x10,OLED_CMD);      //设置显示位置—列高地址

for(n=0;n<128;n++)OLED_WR_Byte(OLED_GRAM[n][i],OLED_DATA);

}

}

void OLED_IIC_START(void)

{

SDA_OUT();   //SDA线输出

OLED_SDIN=1;

OLED_SCLK=1;

delay_us(4);

OLED_SDIN=0;//START:when CLK is high,DATA change form high to low

delay_us(4);

OLED_SCLK=0;//钳住IIC总线,准备发送或者接收数据

}

void OLED_IIC_STOP(void)

{

SDA_OUT();  //SDA线输出

OLED_SCLK=0;

OLED_SDIN=0;//STOP:when CLK is high DATA change form low to high

delay_us(4);

OLED_SCLK=1;

OLED_SDIN=1;//发送I2C总线结束信号

delay_us(4);

}

//等待应答信号到来

//返回值: 1,接收应答失败,停止IIC总线

// 0,接收应答成功

//单片机作为主设备等待从设备的应答信号

u8 OLED_IIC_WAITACK(void)

{

u8 timer=0;

OLED_SDIN=1;delay_us(1);//和开发教程IIC顺序不同

OLED_SCLK=1;delay_us(1);

SDA_IN();      //SDA设置为输入和开发教程IIC顺序不同

while(OLED_SDIN_IN)

{

timer++;

if(timer++>250)

{

OLED_IIC_STOP();

return 1;

}

}

OLED_SCLK=0;//时钟输出0

return 0;

}

//IIC发送一个字节

void MCU_Send_Byte(u8 txd)

{

u8 t;

SDA_OUT();

OLED_SCLK=0;//拉低时钟开始数据传输

for(t=0;t<8;t++)

{

OLED_SDIN=(txd&0x80)>>7;

txd<<=1;

delay_us(4);   //8位二进制依次发送出去

OLED_SCLK=1;

delay_us(4);

OLED_SCLK=0;

delay_us(4);

}

}

//oled中写命令

u8 OLED_WR_CMD(u8 cmd)//

{

OLED_IIC_START();

MCU_Send_Byte(0X78);//发送器件地址0X78, R/W# = 0 写模式

if(OLED_IIC_WAITACK())

return 1;

MCU_Send_Byte(0X00);//0x00代表写命令  0x40带表写数据

if(OLED_IIC_WAITACK())

return 2;

MCU_Send_Byte(cmd);

if(OLED_IIC_WAITACK())

return 3;

OLED_IIC_STOP();

return 0;

}

void OLED_WR_DAT(u8 dat)//

{

OLED_IIC_START();

MCU_Send_Byte(0X78);//发送器件地址0X78, R/W# = 0 写模式

OLED_IIC_WAITACK();

MCU_Send_Byte(0X40);//0x00代表写命令  0x40带表写数据

OLED_IIC_WAITACK();

MCU_Send_Byte(dat);

OLED_IIC_WAITACK();

OLED_IIC_STOP();        //

}

void OLED_WR_Byte(u8 dat,u8 cmd)

{

if(cmd) OLED_WR_DAT(dat);

else OLED_WR_CMD(dat);

}

//开启OLED显示

void OLED_Display_On(void)

{

OLED_WR_Byte(0X8D,OLED_CMD);  //SET DCDC命令

OLED_WR_Byte(0X14,OLED_CMD);  //DCDC ON

OLED_WR_Byte(0XAF,OLED_CMD);  //DISPLAY ON

}

//关闭OLED显示

void OLED_Display_Off(void)

{

OLED_WR_Byte(0X8D,OLED_CMD);  //SET DCDC命令

OLED_WR_Byte(0X10,OLED_CMD);  //DCDC OFF

OLED_WR_Byte(0XAE,OLED_CMD);  //DISPLAY OFF

}

//清屏函数,清完屏,整个屏幕是黑色的!和没点亮一样!!!

void OLED_Clear(void)

{

u8 i,n;

for(i=0;i<8;i++)for(n=0;n<128;n++)OLED_GRAM[n][i]=0X00;

OLED_Refresh_Gram();//更新显示

}

//画点

//x:0~127

//y:0~63

//t:1 填充 0,清空

void OLED_DrawPoint(u8 x,u8 y,u8 t)

{

u8 pos,bx,temp=0;

if(x>127||y>63)return;//超出范围了.

pos=7-y/8;

bx=y%8;

temp=1<

if(t)OLED_GRAM[x][pos]|=temp;

else OLED_GRAM[x][pos]&=~temp;

}

//x1,y1,x2,y2 填充区域的对角坐标

//确保x1<=x2;y1<=y2 0<=x1<=127 0<=y1<=63

//dot:0,清空;1,填充

void OLED_Fill(u8 x1,u8 y1,u8 x2,u8 y2,u8 dot)

{

u8 x,y;

for(x=x1;x<=x2;x++)

{

for(y=y1;y<=y2;y++)OLED_DrawPoint(x,y,dot);

}

OLED_Refresh_Gram();//更新显示

}

//在指定位置显示一个字符,包括部分字符

//x:0~127

//y:0~63

//mode:0,反白显示;1,正常显示

//size:选择字体 12/16/24

void OLED_ShowChar(u8 x,u8 y,u8 chr,u8 size,u8 mode)

{

u8 temp,t,t1;

u8 y0=y;

u8 csize=(size/8+((size%8)?1:0))*(size/2);                //得到字体一个字符对应点阵集所占的字节数

chr=chr-' ';//得到偏移后的值

for(t=0;t

{

if(size==12)temp=asc2_1206[chr][t];                  //调用1206字体

else if(size==16)temp=asc2_1608[chr][t];        //调用1608字体

else if(size==24)temp=asc2_2412[chr][t];        //调用2412字体

else return;                                                                //没有的字库

for(t1=0;t1<8;t1++)

{

if(temp&0x80)OLED_DrawPoint(x,y,mode);

else OLED_DrawPoint(x,y,!mode);

temp<<=1;

y++;

if((y-y0)==size)

{

y=y0;

x++;

break;

}

}

}

}

//m^n函数

u32 mypow(u8 m,u8 n)

{

u32 result=1;

while(n--)result*=m;

return result;

}

//显示2个数字

//x,y :起点坐标

//len :数字的位数

//size:字体大小

//mode:模式        0,填充模式;1,叠加模式

//num:数值(0~4294967295);

void OLED_ShowNum(u8 x,u8 y,u32 num,u8 len,u8 size)

{

u8 t,temp;

u8 enshow=0;

for(t=0;t

{

temp=(num/mypow(10,len-t-1))%10;

if(enshow==0&&t

{

if(temp==0)

{

OLED_ShowChar(x+(size/2)*t,y,' ',size,1);

continue;

}else enshow=1;

}

OLED_ShowChar(x+(size/2)*t,y,temp+'0',size,1);

}

}

void OLED_ShowSmallNum(u8 x,u8 y,u32 num,u8 len,u8 size)

{

u8 t,temp;

for(t=0;t

{

temp=(num/mypow(10,len-t-1))%10;

OLED_ShowChar(x+(size/2)*t,y,temp+'0',size,1);

}

}

void OLED_ShowFloatNum(u8 x,u8 y,float num,u8 len,u8 size)

{

u16 temp_int=0;

u16 temp_float=0;

temp_int=num;  //temp_int保存num的整数部分

temp_float=(num-temp_int)*100;//temp_float保存num的小数部分2位

OLED_ShowNum(x,y,temp_int,4,size);//显示4位整数部分数字

OLED_ShowString(2*size+x,y,".",size);//显示.

OLED_ShowSmallNum((2*size+size/2)+x,y,temp_float,2,size);//显示小数部分

}

//显示字符串

//x,y:起点坐标

//size:字体大小

//*p:字符串起始地址

void OLED_ShowString(u8 x,u8 y,const char *p,u8 size)

{

while((*p<='~')&&(*p>=' '))//判断是不是非法字符!

{

if(x>(128-(size/2))){x=0;y+=size;}

if(y>(64-size)){y=x=0;OLED_Clear();}

OLED_ShowChar(x,y,*p,size,1);

x+=size/2;

p++;

}

}

u8 OLED_Init(void)

{

RCC->APB2ENR|=1<<4;    //使能PORTC时钟

RCC->APB2ENR|=1<<8;    //使能PORTG时钟

GPIOC->CRL&=0XFFFFFFF0; //PC0 OUT IIC模式

GPIOC->CRL|=0X00000003;         //

GPIOC->ODR|=1<<0;        //

GPIOG->CRH&=0X0FFFFFFF;        //RST

GPIOG->CRH|=0X30000000;

GPIOG->ODR|=1<<15;

OLED_RST=0;

delay_ms(100);

OLED_RST=1;

if(!OLED_WR_CMD(0XAE)) printf("1-ok\r\n");

else printf("1-no\r\n");

if(!OLED_WR_CMD(0Xd5)) printf("2-ok\r\n");

else printf("2-no\r\n");

if(!OLED_WR_CMD(80)) printf("3-ok\r\n");

else printf("3-no\r\n");

if(!OLED_WR_CMD(0XA8)) printf("4-ok\r\n");

else printf("4-no\r\n");

if(!OLED_WR_CMD(0X3F)) printf("5-ok\r\n");

else printf("5-no\r\n");

if(!OLED_WR_CMD(0XD3)) printf("6-ok\r\n");

else printf("6-no\r\n");

if(!OLED_WR_CMD(0X00)) printf("7-ok\r\n");

else printf("7-no\r\n");

if(!OLED_WR_CMD(0X40)) printf("8-ok\r\n");

else printf("8-no\r\n");

if(!OLED_WR_CMD(0X8D)) printf("9-ok\r\n");

else printf("9-no\r\n");

if(!OLED_WR_CMD(0X14)) printf("10-ok\r\n");

else printf("10-no\r\n");

if(!OLED_WR_CMD(0X20)) printf("11-ok\r\n");

else printf("11-no\r\n");

if(!OLED_WR_CMD(0X02)) printf("12-ok\r\n");

else printf("12-no\r\n");

if(!OLED_WR_CMD(0XA1)) printf("13-ok\r\n");

else printf("13-no\r\n");

if(!OLED_WR_CMD(0XC0)) printf("14-ok\r\n");

else printf("14-no\r\n");

if(!OLED_WR_CMD(0XDA)) printf("15-ok\r\n");

else printf("15-no\r\n");

if(!OLED_WR_CMD(0X12)) printf("16-ok\r\n");

else printf("16-no\r\n");

if(!OLED_WR_CMD(0X81)) printf("17-ok\r\n");

else printf("17-no\r\n");

if(!OLED_WR_CMD(0XEF)) printf("18-ok\r\n");

else printf("18-no\r\n");

if(!OLED_WR_CMD(0XD9)) printf("19-ok\r\n");

else printf("19-no\r\n");

if(!OLED_WR_CMD(0XF1)) printf("20-ok\r\n");

else printf("20-no\r\n");

if(!OLED_WR_CMD(0XDB)) printf("21-ok\r\n");

else printf("21-no\r\n");

if(!OLED_WR_CMD(0X30)) printf("22-ok\r\n");

else printf("22-no\r\n");

if(!OLED_WR_CMD(0XA4)) printf("23-ok\r\n");

else printf("23-no\r\n");

if(!OLED_WR_CMD(0XA6)) printf("24-ok\r\n");

else printf("24-no\r\n");

if(!OLED_WR_CMD(0XAF)) printf("25-ok\r\n");

else printf("25-no\r\n");

OLED_Clear();

return 0;

}

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

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

相关文章

C#数据结构-单链表

理论基础&#xff1a; 链表是用一组任意的存储单元来存储线性表中的数据元素。 如果结点的引用域只存储该结点直接后继结点的存储地址&#xff0c;则该链表叫单链表(Singly Linked List)。 单链表由头引用H唯一确定。头引用指向单链表的第一个结点&#xff0c;也就是把单链表第…

[Golang] string类型和其他类型的值的互转

问题 由于在开发过程中遇到类型转换问题&#xff0c;比如在web中某个参数是以string存在的&#xff0c;这个时候需要转换成其他类型&#xff0c;这里官方的strconv包里有这几种转换方法。 实现 有两个函数可以实现类型的互转&#xff08;以int转string为例&#xff09; 1. For…

pandas 根据单号分类_由 “猫捉老鼠”游戏联想的用户分类问题

一、说在最前 用户识别&#xff0c;用户分类&#xff0c;精准营销…这是咱们业务人员常常念叨的话。底层逻辑为无论任何营销目的&#xff0c;在营销手段上&#xff0c;越针对某一细化群体&#xff0c;达成目的的概率也就会越大。那今天就来和大家说道说道用户识别/分类的一种方…

python解释器环境中、用于表示上一次_文学人类学概说_尔雅文学人类学概说答案第四小节课后作业答案...

【判断题】对零星分数的统计资料&#xff0c;经过统计分组整理后&#xff0c;仍然不能发现其特点和规律。【单选题】小明一家三口在食用自制的臭豆腐后&#xff0c;相继出现全身乏力、头晕、头痛&#xff0c;继而出现视力模糊、眼睑下垂、复视、吞咽困难等症状&#xff0c;他们…

[Golang]slice的用法以及和数组的区别

说明 slice是go的一个语言特性&#xff0c;其实有点类似于cpp的vector&#xff0c;可变长度&#xff0c;可以扩展空间。今天详细看了下&#xff0c;做下总结。 slice本质上是一个区间&#xff0c;原型是[]T,大致的实现是这样的&#xff1a; type slice struct {first *Tlen i…

IE Firefox通用DOM

要写出在各大主流浏览器上都兼容的JS代码&#xff0c;就要关注他们的区别&#xff0c;下是IE和FF综合考虑的通用DOM&#xff01; 1.document.formName.item("itemName") 问题说明:IE下,可以使用document.formName.item("itemName")或document.formName.ele…

arraylist从大到小排序_java基础算法之二叉树排序(递归)

一、二叉树介绍在计算机科学中&#xff0c;二叉树是每个结点最多有两个子树的树结构。二叉树由各种节点组成&#xff0c;如下图所示&#xff1a;每个节点都可以有左子节点&#xff0c;右子节点每一个节点都有一个值二叉树遍历&#xff1a;二叉树的遍历分左序&#xff0c;中序&a…

uvm 形式验证_IC设计职位详解之“数字验证工程师”就业必学课程

数字验证处于数字IC设计流程的前端&#xff0c;属于数字IC设计类岗位的一种。在IC设计中&#xff0c;数字验证所占的人数比重是非常多的&#xff0c;很多大公司&#xff0c;数字前端设计工程师与验证工程师的比例已经达到1&#xff1a;3。数字验证主要分成几种层次的验证&#…

[Golang]slice值传递存在的问题

说明 因为slice是指针类型&#xff0c;所以很多人会误以为其传递的是引用&#xff0c;所以在使用的过程中会出现一些非期望的实现。 问题 在使用append函数时&#xff0c;比如以下函数&#xff1a; func sliceModify(slice []int) {// slice[0] 88slice append(slice, 6) } …

IE8给你选择的理由

记得第一次用电脑时的情景&#xff0c;有点兴奋&#xff0c;双手不知道往哪里放&#xff0c;还有点局促和不安&#xff0c;怕不小心弄坏了它。也记得第一次上网&#xff0c;那个时候的上网就是用浏览器去访问在线聊天室&#xff0c;去和不认识的人去聊天&#xff0c;在网络信息…

流畅的python目录_流畅的python python 序列

内置序列 容器类型 list 、tuple和collections.deque这些序列能放入不同的类型的数据 扁平序列 str、byets、bytearray、memoryview(内存视图)和array.array(数组) 可变序列 list、bytearray、array.array、collections.deque和memoryview 不可变序列 tuple、str和bytes 可变序…

[Golang] 用interface{}实现泛型出现的问题

说明 在做一些实现的时候&#xff0c;碰到了一个棘手的问题&#xff0c;问题是这样的&#xff0c;向一个函数里传入slice和begin,end,返回slice[begin:end]。很明显这是一个实现泛型的问题&#xff0c;但是在做具体实现的时候出现问题。 问题 根据问题&#xff0c;很容易写下如…

dwf怎么合成一个_将ActionForm拼合成一条插入和更新语句

package chs.jhsyss.form;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;import java.util.Date;public class Waper {public Waper(){}/*** 本方法用于将FORM对象组装成一条INSERT语句* param obj ActionForm 以及其子对象* param for…

WebHelper类

成员一&#xff1a;获取上下文对象&#xff1a; public static HttpContext GetContext() { HttpContext context HttpContext.Current; if (context null) { throw new Exception("HttpContext not found"…

关联查询数据重复怎么办_在设计数据表的时候,是一个宽表好,还是多个维度表好?...

数据仓库每张表的搭建&#xff0c;主要依赖于这个表在整个数据仓库中的作用和相关意义。首先要清楚这个表的存在是为了解决那些问题&#xff0c;什么角色使用&#xff0c;怎么保证使用者尽可能好的体验解决问题。从以上所提到的角度去看待问题&#xff0c;拆解以下几点因素&…

[Beego] [bootstrap-paginator]实现分页功能

说明 在开发中分页功能几乎是必不可少的一项功能&#xff0c;使用beego框架开发时&#xff0c;就遇到了分页功能的需求。可能是之前版本并不支持&#xff0c;我发现有很多自己实现的分页功能的封装&#xff0c;在阅读了官方源码时&#xff0c;我发现了分页功能的封装&#xff0…

电磁波传播相位是否会变化_相位常数β与波数k是一回事吗?

1.相位常数β与波数k先明确一点&#xff1a;相位常数是指传输线&#xff0c;而波数是指平面波。1.1. 波数k wavenumber波数k&#xff1a;单位长度上有多少弧度&#xff1f;Jun.14.2019电磁波在材料中以光速 运动&#xff1a;材料的磁导率&#xff1a;材料的介电常数in free spa…

c#获取系统时间的方法

转:http://bbs.bc-cn.net/viewthread.php?tid238469 //今天DateTime.Now.Date.ToShortDateString();//昨天&#xff0c;就是今天的日期减一DateTime.Now.AddDays(-1).ToShortDateString();//明天&#xff0c;同理&#xff0c;加一DateTime.Now.AddDays(1).ToShortDateString()…

用python画出叶子_太疯狂了!原来用粉笔画画,也可以这么美,简单几招教你,美到邻居羡慕嫉妒...

......点进来之前先让大家瞧瞧相信这是用粉笔画的吗&#xff1f;▼玫瑰花▼山茶花▼蓝色鸢尾花▼樱花树▼这一张张让人直流鼻血的作品没错这就是用色粉笔画出来的很多人问&#xff1a;是不是平时老师上课时用的粉笔呢&#xff1f;这里给大家科普下&#xff1a;色粉画&#xff0…

jsonp react 获取返回值_必须要会的 50 个React 面试题(下)

翻译&#xff1a;疯狂的技术宅原文&#xff1a;https://www.edureka.co/blog/interview-questions/react-interview-questions29. 你对受控组件和非受控组件了解多少&#xff1f;受控组件非受控组件1. 没有维持自己的状态1. 保持着自己的状态2.数据由父组件控制2.数据由 DOM 控…