备注:在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通信知识汇总相关推荐

  1. STM32和ROS串口通信常见问题汇总答疑

    STM32和ROS串口通信常见问题汇总答疑 大家好,我是白茶清欢,最近看了博客文章<stm32和ros的串口通信>有很多问题的评论,这里汇总回复一下. 问题1:运行时报错如下: rosru ...

  2. STM32—OLED显示屏

    3. OLED显示屏 本文来自于<STM32--江科大>的笔记整理. 文章目录 3. OLED显示屏 3.1 OLED简介 3.2 OLED驱动函数 代码: OLED.h OLED.c O ...

  3. 关于STM32+OLED显示屏的简单应用

    文章目录 一.题目要求 二.SPI通信协议相关介绍 1. SPI 协议简介 2.STM32 的 SPI 特性及架构 3.STM32 的 SPI 外设简介 4. STM32 的 SPI 架构剖析 5. ...

  4. 蜂窝通信知识汇总(包括LTE和NR5G) --目录

    GSM GSM基础知识 GSM/GPRS基础汇总 GSM协议栈结构和GSM.GPRS信道映射 GSM系统消息 GSM/GPRS/EGPRS相关调制方式/速率 GSM 协议索引 GPRS Operati ...

  5. STM32 网口转SPI通信

    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言 一.网络通信与SPI通信是什么? 二.代码思路 1.流程图 三.测试代码流程与关键代码 总结 前言 `本文介绍利用ST ...

  6. STM32 OLED显示屏

    OLED概念 一:屏幕的分类 OLED屏 -- 有机发光二极管 当通上电的时候,管道内的有机材料就会发光 投射出红蓝绿三种颜色的光,并且每个单元都是独立工作,所以显示出来得画面,是的屏幕会更加得饱满: ...

  7. 2018 0612 ----最小系统STM32 + oled(SPi连接)

    内容:利用最小系统STM32f103CB点亮OLED液晶屏幕 OLED使用的是有7个引脚的分别为的:GND .VCC.D0.D0.RES.DC.CS 其中OLED与STM32的硬件连接: D0---- ...

  8. STM32:OLED显示屏代码

    main.c主函数部分代码: #include "stm32f10x.h"                  // Device header #include "Del ...

  9. STM32 7针0.96寸OLED显示屏(硬件SPI+DMA)无需内核响应 超高刷新率!

    芯片:STM32f103c8t6 f103型号大同小异,其他芯片请根据情况修改接口和配置 使用的是7针的0.96寸OLED屏幕,黑白两色显示 以下是实物图 一.原理: 首先你要了解STM32上的AFI ...

最新文章

  1. mac 使用homebrew 安装mysql
  2. SAP QM 采样方案的c1 d1 c2 d2 --多重采样
  3. retinaface精度
  4. 河南民办计算机大学排名,2020年河南最好的民办大学最新排名
  5. [国家集训队]最长双回文串 manacher
  6. SCOM 2012系列⑨单台服务器拓扑监控
  7. 开源软件加密授权方案_身份验证和授权作为开源解决方案服务
  8. Hive的10种常用优化总结,再也不怕MapReduce分配不均了
  9. visualmap超过范围改变颜色_换种颜色,换种心情——车身改色
  10. Android之离线词典
  11. Animation动画详解
  12. The Design of Model (part 1)
  13. 增长工程日 | 从战略到战术,如何搭建新消费品牌增长体系
  14. Mysql ERROR: 1253 解决方法
  15. 支付宝二维码支付文档,找了好久,记在这里
  16. 字典树 ZJM 与生日礼物
  17. c语言中swap的意思,C语言中swap的作用和用法?
  18. Windows10字符映射表的搜索功能
  19. 仿牛客项目(持续更新)
  20. 西邮计算机网络实验,2018ThoughtWorks西邮实验室纳新题

热门文章

  1. HEVC学习(一) —— HM的使用
  2. Vue-组件嵌套之——父组件向子组件传值
  3. Servlet_Jsp学习笔记:
  4. 6687. 【JZOJ 省选模拟】树没了(tree)
  5. BIM技术在住宅园区物业管理中的应用及其优势
  6. 从头开始实现一个小型spring框架——手写Spring之集成Tomcat服务器
  7. ipad 3.2.2 IPAD 越狱教程
  8. 扫码枪在中文输入法下扫描乱码问题
  9. 小米平板android版本,想要翻身还需努力 小米平板2安卓版评测
  10. MongoDB在58同城的应用实践