STM32 OLED显示屏--SPI通信知识汇总
备注:在OLED显示屏部分,单片机是通过SPI和OLED进行通信的。
文章目录
目录
文章目录
一、SPI时序通信
二、SPI通信的分类
1.硬件SPI
2.软件SPI
三、硬件SPI
SPI特性
硬件SPI引脚说明
库函数初始化
以下是本篇文章正文内容,下面案例可供参考
一、SPI时序通信
在此功能中,采用的是四线SPI,我们在开发过程中,应该去寻扎数据手册里面的通信时序图,才能使得单片机利用四线SPI和OLED进行通信的功能操作。
小结:在时序通信的过程张,高位先发,且当时钟线SCLK为低电平的时候,就可以吧数据放到数据线上面将其数据发(SDIN)。
二、SPI的分类
1.软件SPI
对于软件SPI的定义是:采用高低电平模拟SPI通信时序来完成发送或者接收数据。对于软件SPIeryan1,这样的通信方式在于移植灵活,引脚使用灵活,只需要任意四个I/O口就可以进行功能的完成,但是其缺点也很明显,那就是速度比较慢。
2.硬件SPI
对于硬件SPI的解释是,由单片机内部自主控制数据的发送与接收,硬件SPI的优点是速度快,单片机可以自主控制,我们只要完成将数据给到单片机,就可以了。缺点是:接口引脚相对固定,没有那么灵活。但是这是开发过程中最为经典的一部分,往下都是介绍硬件SPI.
三、硬件SPI
1、SPI的特性
硬件SPI特性有:是一个三线全双工的同步传输,可以带有或者不带第三条双线数据线的双线单工同步传输、可以进行8或者16位传输帧格式选择,能搞实现主机或者从机操作,并且支持多个主控模式,可以进行编程的时钟极性和相位,可以进行数据顺序编程,MSB在前或者LSB在前,可以触发中断的专用发送和收发标准,支持可靠通信的硬件CRC。
2、对四大引脚进行解释说明
MISO引脚:主设备输入,从设备输出引脚,该引脚的功能是在从机模式下发送数据,在主机模式下接收数据;
MOSI引脚:主设备输出,从设备输入引脚,该引脚的功能时在主机模式下发送数据,在从机模式下接收数据;
SCK引脚:是串口时钟引脚,该引脚的功能时主设备输出,从设备的输入;
NSS引脚:名为片选引脚,该功能是从设备选择,这一一个可以进行选择的引脚,用来选择主机、从机设备,可以让主设备进行单独的和特定的设备进行通信,并且可以避免和数据线发生冲突,片选引脚,我们一般不采用硬件的片选,我们可以进行手动对片选的控制。
3、库函数初始化
初始化引脚--
需要关闭PA15的JTAG功能,因为PA15复位I/O口不可用--
GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitTypeDef SPI2_SCLK_MOSI;SPI_InitTypeDef SPI_InitStruct;RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);//JTAG默认为下载接口 我们需要通过复用为普通的IOGPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE);//使其生效为普通IO口
初始化结构体
SPI2_SCLK_MOSI.GPIO_Mode = GPIO_Mode_AF_PP; //设置功能模式为推挽复用功能SPI2_SCLK_MOSI.GPIO_Pin = GPIO_Pin_13|GPIO_Pin_15; //设置引脚配置SPI2_SCLK_MOSI.GPIO_Speed= GPIO_Speed_50MHz; //设置速度GPIO_Init(GPIOB, &SPI2_SCLK_MOSI); //初始化spi2的sclk_mosi方面SPI2_SCLK_MOSI.GPIO_Mode = GPIO_Mode_IN_FLOATING; //设置为上升沿SPI2_SCLK_MOSI.GPIO_Pin = GPIO_Pin_14; //SPI2_SCLK_MOSI.GPIO_Speed= GPIO_Speed_50MHz; //a072O+45GPIO_Init(GPIOB, &SPI2_SCLK_MOSI); SPI_InitStruct.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2;//2分频最大速度36MSPI_InitStruct.SPI_CPHA = SPI_CPHA_2Edge;//第二个时钟边沿的上升沿采样SPI_InitStruct.SPI_CPOL = SPI_CPOL_High;//CLK空闲时为高电平SPI_InitStruct.SPI_CRCPolynomial = 7;//STM32的SPI带硬件eccSPI_InitStruct.SPI_DataSize = SPI_DataSize_8b;//8位数据位SPI_InitStruct.SPI_Direction = SPI_Direction_2Lines_FullDuplex;//全双工模式SPI_InitStruct.SPI_FirstBit = SPI_FirstBit_MSB;//高位在前先发SPI_InitStruct.SPI_Mode = SPI_Mode_Master;//主机模式SPI_InitStruct.SPI_NSS = SPI_NSS_Hard;//CS硬件管理 我们自己控制SPI_Init(SPI2,&SPI_InitStruct);SPI_Cmd(SPI2, ENABLE);
完整代码
OLED.c
#include "oled.h"
#include "stdlib.h"
#include "oledfont.h"
#include "delay.h"u8 OLED_GRAM[144][8];u8 SPI2_Send_Byte(u8 data)
{while(!(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE)==SET));//获取发送完成标志位SPI_I2S_SendData(SPI2, data);//spi发送一个字节while(!(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE)==SET));//获取接收完成标志位return SPI_I2S_ReceiveData(SPI2);//spi读一个字节
}void OLED_WR_Byte(u8 dat,u8 cmd)
{ u8 i; if(cmd)OLED_DC_Set();elseOLED_DC_Clr();OLED_CS_Clr();SPI2_Send_Byte(dat); OLED_CS_Set();OLED_DC_Set();
}//更新显存到OLED
void OLED_Refresh(void)
{u8 i,n;for(i=0;i<8;i++){OLED_WR_Byte(0xb0+i,OLED_CMD); //设置行起始地址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_Clear(void)
{u8 i,n;for(i=0;i<8;i++){for(n=0;n<128;n++){OLED_GRAM[n][i]=0;//清除所有数据}}OLED_Refresh();//更新显示
}//配置写入数据的起始位置
void OLED_WR_BP(u8 x,u8 y)
{OLED_WR_Byte(0xb0+y,OLED_CMD);//设置行起始地址OLED_WR_Byte(((x&0xf0)>>4)|0x10,OLED_CMD);//设置列起始地址OLED_WR_Byte((x&0x0f),OLED_CMD);
}//显示单个字符
//x:0~127
//y:0~7
//chr:传入的字符
void OLED_ShowChar(u8 x,u8 y,char chr,u8 size)//chr = 'A' chr = 65
{int i;u8 j;u8 page = size/8;//计算字符12 16 24 大小所需要显示页数if(size%8 !=0) page+=1;//有余数 说明还要加多一页for(j=0;j<page;j++){OLED_WR_BP(x,y+j);//先确定开始位置for(i=0;i<size/2;i++){if(size == 12) OLED_WR_Byte(F12x6[(chr-32)*12+i + j*size/2],OLED_DATA);else if(size == 16) OLED_WR_Byte(F16x8[(chr-32)*16+i + j*size/2],OLED_DATA);else if(size == 24) OLED_WR_Byte(F24x12[(chr-32)*36+i + j*size/2],OLED_DATA);}}
}//显示一串字符
void OLED_Show_String(u8 x,u8 y,char *ch,u8 size)
{u8 page = size/8;//计算字符12 16 24 大小所需要显示页数if(size%8 !=0) page+=1;//有余数 说明还要加多一页while(*ch != 0){OLED_ShowChar(x,y,*ch,size);x = x+size/2;//移动位置 显示下一个字符ch++;if(x>127){x = 0;//坐标归0 下一行显示y+=page;//页数相加}}
}//OLED显示一个汉字
void OLED_Show_One_Chinese(u8 x,u8 y,char ch[])
{u16 i = 0;int k;while(1){if((ch[0] == GB2312_font[i][0]) && (ch[1]==GB2312_font[i][1])){OLED_WR_BP(x,y);for(k=0;k<16;k++){OLED_WR_Byte(GB2312_16x16[i*32+k],OLED_DATA);//发送字符数据的上半部分}OLED_WR_BP(x,y+1);//页数+1 改变显示位置for(;k<32;k++){OLED_WR_Byte(GB2312_16x16[i*32+k],OLED_DATA);//发送字符数据的上半部分}break;}i++;if(i >= (sizeof(GB2312_font)/3)) break;//超过字库大小 说明没有搜索到相应的汉字}
}
//13397813910
//OLED的初始化//BMP[]:要写入的图片数组
void OLED_ShowPicture(u8 x0,u8 y0,u8 x1,u8 y1,u8 BMP[])
{u16 j=0;u8 x=0,y=0;if(y%8==0)y=0;else y+=1;for(y=y0;y<y1;y++){OLED_WR_BP(x0,y);for(x=x0;x<x1;x++){OLED_WR_Byte(BMP[j],OLED_DATA);j++;}}
}//实现滚动的功能
void OLED_ScrollDisplay(u8 num,u8 space)
{u8 i,n,t=0,m=0,r;while(1){if(m==0){OLED_Show_One_Chinese(10,2,6); //写入一个汉字保存在OLED_GRAM[][]数组中t++;}if(t==num){for(r=0;r<16*space;r++) //显示间隔{for(i=0;i<144;i++){for(n=0;n<8;n++){OLED_GRAM[i-1][n]=OLED_GRAM[i][n];}}OLED_Refresh();}t=0;}m++;if(m==16){m=0;}for(i=0;i<144;i++) //实现左移{for(n=0;n<8;n++){OLED_GRAM[i-1][n]=OLED_GRAM[i][n];}}OLED_Refresh();}
}void OLED_Init(void)
{GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitTypeDef SPI2_SCLK_MOSI;SPI_InitTypeDef SPI_InitStruct;RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);//JTAG默认为下载接口 我们需要通过复用为普通的IOGPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE);//使其生效为普通IO口//PA4---复位 PA15 命令/数据RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //使能A端口时钟,开启时钟GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4|GPIO_Pin_15; //配置引脚GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //速度50MHzGPIO_Init(GPIOA, &GPIO_InitStructure); //初始化GPIOD3,6GPIO_SetBits(GPIOA,GPIO_Pin_4|GPIO_Pin_15); //设置空闲时间为高电平//PB7---片选线RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); //使能A端口时钟GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7; //设置引脚配置引脚7GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//速度50MHzGPIO_Init(GPIOB, &GPIO_InitStructure); //初始化GPIOD3,6GPIO_SetBits(GPIOB,GPIO_Pin_7); //空闲默认高电平SPI2_SCLK_MOSI.GPIO_Mode = GPIO_Mode_AF_PP; //设置功能模式为推挽复用功能SPI2_SCLK_MOSI.GPIO_Pin = GPIO_Pin_13|GPIO_Pin_15; //设置引脚配置SPI2_SCLK_MOSI.GPIO_Speed= GPIO_Speed_50MHz; //设置速度GPIO_Init(GPIOB, &SPI2_SCLK_MOSI); //初始化spi2的sclk_mosi方面SPI2_SCLK_MOSI.GPIO_Mode = GPIO_Mode_IN_FLOATING; //设置为上升沿SPI2_SCLK_MOSI.GPIO_Pin = GPIO_Pin_14; //SPI2_SCLK_MOSI.GPIO_Speed= GPIO_Speed_50MHz; //a072O+45GPIO_Init(GPIOB, &SPI2_SCLK_MOSI); SPI_InitStruct.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2;//2分频最大速度36MSPI_InitStruct.SPI_CPHA = SPI_CPHA_2Edge;//第二个时钟边沿的上升沿采样SPI_InitStruct.SPI_CPOL = SPI_CPOL_High;//CLK空闲时为高电平SPI_InitStruct.SPI_CRCPolynomial = 7;//STM32的SPI带硬件eccSPI_InitStruct.SPI_DataSize = SPI_DataSize_8b;//8位数据位SPI_InitStruct.SPI_Direction = SPI_Direction_2Lines_FullDuplex;//全双工模式SPI_InitStruct.SPI_FirstBit = SPI_FirstBit_MSB;//高位在前先发SPI_InitStruct.SPI_Mode = SPI_Mode_Master;//主机模式SPI_InitStruct.SPI_NSS = SPI_NSS_Hard;//CS硬件管理 我们自己控制SPI_Init(SPI2,&SPI_InitStruct);SPI_Cmd(SPI2, ENABLE);Delay_ms(200);OLED_RST_Clr();//复位Delay_ms(200);OLED_RST_Set();OLED_WR_Byte(0xAE,OLED_CMD);//--turn off oled panelOLED_WR_Byte(0x00,OLED_CMD);//---set low column addressOLED_WR_Byte(0x10,OLED_CMD);//---set high column addressOLED_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 registerOLED_WR_Byte(0xCF,OLED_CMD);// Set SEG Output Current BrightnessOLED_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 displayOLED_WR_Byte(0xA8,OLED_CMD);//--set multiplex ratio(1 to 64)OLED_WR_Byte(0x3f,OLED_CMD);//--1/64 dutyOLED_WR_Byte(0xD3,OLED_CMD);//-set display offset Shift Mapping RAM Counter (0x00~0x3F)OLED_WR_Byte(0x00,OLED_CMD);//-not offsetOLED_WR_Byte(0xd5,OLED_CMD);//--set display clock divide ratio/oscillator frequencyOLED_WR_Byte(0x80,OLED_CMD);//--set divide ratio, Set Clock as 100 Frames/SecOLED_WR_Byte(0xD9,OLED_CMD);//--set pre-charge periodOLED_WR_Byte(0xF1,OLED_CMD);//Set Pre-Charge as 15 Clocks & Discharge as 1 ClockOLED_WR_Byte(0xDA,OLED_CMD);//--set com pins hardware configurationOLED_WR_Byte(0x12,OLED_CMD);OLED_WR_Byte(0xDB,OLED_CMD);//--set vcomhOLED_WR_Byte(0x40,OLED_CMD);//Set VCOM Deselect LevelOLED_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/disableOLED_WR_Byte(0x14,OLED_CMD);//--set(0x10) disableOLED_WR_Byte(0xA4,OLED_CMD);// Disable Entire Display On (0xa4/0xa5)OLED_WR_Byte(0xA6,OLED_CMD);// Disable Inverse Display On (0xa6/a7) OLED_WR_Byte(0xAF,OLED_CMD);OLED_Clear();
}
STM32 OLED显示屏--SPI通信知识汇总相关推荐
- STM32和ROS串口通信常见问题汇总答疑
STM32和ROS串口通信常见问题汇总答疑 大家好,我是白茶清欢,最近看了博客文章<stm32和ros的串口通信>有很多问题的评论,这里汇总回复一下. 问题1:运行时报错如下: rosru ...
- STM32—OLED显示屏
3. OLED显示屏 本文来自于<STM32--江科大>的笔记整理. 文章目录 3. OLED显示屏 3.1 OLED简介 3.2 OLED驱动函数 代码: OLED.h OLED.c O ...
- 关于STM32+OLED显示屏的简单应用
文章目录 一.题目要求 二.SPI通信协议相关介绍 1. SPI 协议简介 2.STM32 的 SPI 特性及架构 3.STM32 的 SPI 外设简介 4. STM32 的 SPI 架构剖析 5. ...
- 蜂窝通信知识汇总(包括LTE和NR5G) --目录
GSM GSM基础知识 GSM/GPRS基础汇总 GSM协议栈结构和GSM.GPRS信道映射 GSM系统消息 GSM/GPRS/EGPRS相关调制方式/速率 GSM 协议索引 GPRS Operati ...
- STM32 网口转SPI通信
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言 一.网络通信与SPI通信是什么? 二.代码思路 1.流程图 三.测试代码流程与关键代码 总结 前言 `本文介绍利用ST ...
- STM32 OLED显示屏
OLED概念 一:屏幕的分类 OLED屏 -- 有机发光二极管 当通上电的时候,管道内的有机材料就会发光 投射出红蓝绿三种颜色的光,并且每个单元都是独立工作,所以显示出来得画面,是的屏幕会更加得饱满: ...
- 2018 0612 ----最小系统STM32 + oled(SPi连接)
内容:利用最小系统STM32f103CB点亮OLED液晶屏幕 OLED使用的是有7个引脚的分别为的:GND .VCC.D0.D0.RES.DC.CS 其中OLED与STM32的硬件连接: D0---- ...
- STM32:OLED显示屏代码
main.c主函数部分代码: #include "stm32f10x.h" // Device header #include "Del ...
- STM32 7针0.96寸OLED显示屏(硬件SPI+DMA)无需内核响应 超高刷新率!
芯片:STM32f103c8t6 f103型号大同小异,其他芯片请根据情况修改接口和配置 使用的是7针的0.96寸OLED屏幕,黑白两色显示 以下是实物图 一.原理: 首先你要了解STM32上的AFI ...
最新文章
- mac 使用homebrew 安装mysql
- SAP QM 采样方案的c1 d1 c2 d2 --多重采样
- retinaface精度
- 河南民办计算机大学排名,2020年河南最好的民办大学最新排名
- [国家集训队]最长双回文串 manacher
- SCOM 2012系列⑨单台服务器拓扑监控
- 开源软件加密授权方案_身份验证和授权作为开源解决方案服务
- Hive的10种常用优化总结,再也不怕MapReduce分配不均了
- visualmap超过范围改变颜色_换种颜色,换种心情——车身改色
- Android之离线词典
- Animation动画详解
- The Design of Model (part 1)
- 增长工程日 | 从战略到战术,如何搭建新消费品牌增长体系
- Mysql ERROR: 1253 解决方法
- 支付宝二维码支付文档,找了好久,记在这里
- 字典树 ZJM 与生日礼物
- c语言中swap的意思,C语言中swap的作用和用法?
- Windows10字符映射表的搜索功能
- 仿牛客项目(持续更新)
- 西邮计算机网络实验,2018ThoughtWorks西邮实验室纳新题