传送门:第一篇入门创建工程:MSP432学习01--新建keil空工程_Kindred。的博客-优快云博客
本文所会用到的附件:
链接:https://pan.baidu.com/s/1nuaua9iP-zPtb_3-ATP2gw?pwd=hr7j
提取码:hr7j
看这一节的前提是你已经建立好相应的工程文件,并且对于MSP432官方的驱动库有一定的熟悉程度。这篇文章旨在分享对于一个陌生的模块,如何创建一个属于自己的硬件库的过程。
最开始是创建文件过程,
新建.c和.h文件,以及将他们添加进项目,这里不再赘述,相信大家应该都清楚,主要强调一个习惯:每一个代码文件和每一个函数都要有自己的说明,这样不仅是为了别人的可读性,也为了自己隔几天还能看懂QAQ
以oled屏幕(SSD1306)的驱动为例,这里使用硬件I2C驱动。
这里记两个小知识点:
1.首先是SPI总线和I2C总线的区别(参考I2C和SPI简介_sunxiaolin2016的博客-优快云博客_i2c与spi:
I2C线序:
- SDA(串行数据线),I2C总线的数据信号线;
- SCL(串行时钟线),时钟信号线。
- VCC,电压,典型电压为+5V或+3.3V
- GND,接地
SPI线序:
- SCLK,串行时钟(主机输出)
- SSEL,Slave,从设备使能信号,由主设备控制
- MOSI,Master output Slave input, 主设备数据输出,从设备数据输入
- MISO,Master input Slave output,主设备数据输入,从设备数据输出
- GND,接地
I2C工作原理
I2C总线在传送数据过程中共有三种类型信号,分别是:开始信号,结束信号和应答信号。
开始信号,SCL为高电平时,SDA由高电平向低电平跳变,开始传送数据。
结束信号,SCL为高电平时,SDA由低电平向高电平跳变,结束传送数据。
应答信号,接收数据的IC在接收到8bit数据后,向发送数据的IC发出特定的低电平脉冲,表示已经收到数据。CPU向受控单元发出一个信号后,等待受控单元发出一个应答信号,CPU接收到应答信号后,根据实际情况作出是否继续传递信号的判断。若未能收到应答信号,则判断为受控单元出现故障。
SPI工作原理
为了开始通信,总线主控器使用从属设备支持的频率来配置时钟。然后,主机在选择线上选择逻辑电平为0的从机。如果需要等待时间,例如模数转换,则主机必须在发出时钟周期之前至少等待该时间段。
在每个SPI时钟周期内,都会发生全双工数据传输。主机在MOSI线上发送一个位,从机读取它;而从机在MISO线上发送一个位,主机读取它。
传输通常涉及两个给定字长的移位寄存器,例如八位,一个在主机中,一个在从机中。它们以虚拟环形拓扑连接。数据通常先移出最高有效位。在时钟沿,主机和从机都移出一点并在传输线上输出到对方。在下一个时钟沿,在每一个接收器处,从传输线采样该位,并将其设置为移位寄存器的新的最低有效位。在寄存器位移入和移出后,主设备和从设备已交换了寄存器值。如果需要交换更多数据,请重新加载位移寄存器,然后重复该过程。传输可以持续任何数量的时钟周期。完成后,主机停止切换时钟信号。
传输通常由八位字组成。但是,其他字长也很常见。例如,用于触摸屏控制器或者音频解码器的16位字,也有一些ADC是12位字。
————————————————
2.然后下面是硬件I2C和模拟I2C的区别(参考硬件I2C与模拟I2C_JYU_hsy的博客-优快云博客_硬件i2c:
硬件I2C对应芯片上的I2C外设,有相应I2C驱动电路,其所使用的I2C管脚也是专用的,因而效率要远高于软件模拟的I2C;一般也较为稳定,但是程序较为繁琐。
硬件(固件)I2C是直接调用内部寄存器进行配置;而软件I2C是没有寄存器这个概念的。
软件I2C一般是使用GPIO管脚,用软件控制SCL,SDA线输出高低电平,模拟i2c协议的时序。
主要对比:
1.硬件IIC用法比较复杂,模拟IIC的流程更清楚一些。
2.硬件IIC速度比模拟快,并且可以用DMA
3.模拟IIC可以在任何管脚上,而硬件只能在固定管脚上。
再讲OLED屏幕显示的原理(主要是数据储存和显示的形式与方法):
数据存储在oled内置的RAM中,我们常见的寻址方式是这种:
也就是说一页实际上对应了屏幕上的8行,而实际上只能选择精确到从哪一页开始(0-7)而不是从哪一行开始(0-63),这也导致了可以显示的字体高度是8的整数倍。
先放上SSD1306的手册,锻炼自己阅读手册的能力,接下来需要用到:https://cdn-shop.adafruit.com/datasheets/SSD1306.pdf
举几个典型的函数的例子:
首先是OLED_WR_Byte函数,之后会一直用到这个函数,本质是用I2C发送数据,这个函数起到的作用是判定这个字节是命令还是数据,参考下面的数据手册的内容,代码如下
//发送一个字节
//向SSD1306写入一个字节。
//mode:数据/命令标志 0,表示命令;1,表示数据;
void OLED_WR_Byte(uint8_t dat, uint8_t mode)
{
if (mode)
MAP_I2C_masterSendMultiByteStart(EUSCI_BX, 0x40);
else
MAP_I2C_masterSendMultiByteStart(EUSCI_BX, 0x00);
MAP_I2C_masterSendMultiByteFinish(EUSCI_BX, dat);
}
接着是开启oled显示的函数OLED_Display_On(void),根据数据手册代码如下
0XA6:正常显示,0XA7反显
/**
*@brief reverse the color
*@param 0:normal 1:reverse
*@retval None
*/
//反显函数
void OLED_ColorTurn(uint8_t i)
{
if (i == 0)
{
OLED_WR_Byte(0xA6, OLED_CMD); //正常显示
}
if (i == 1)
{
OLED_WR_Byte(0xA7, OLED_CMD); //反色显示
}
}
最后是在指定位置显示一个字符 OLED_ShowChar,需要用到另一个函数OLED_Set_Pos,先解释OLED_Set_Pos,0xb0+y即从第y页开始,根据前面讲到的oled的显存共8页(0-7),每页128列(0-127),如设置第100行,x=0x64,低位(x & 0xf0) >> 4) | 0x10 = 0x16,取6,高位(x & 0x0f) = 0x04,取4,最后即为0x64,第100行。代码如下:
/**
*@brief set the coordinates(before displaying)
*@param x[0, 127], y[0,7] position in the oled RAM
*@retval None
*/
//坐标设置
void OLED_Set_Pos(uint8_t x, uint8_t y)
{
OLED_WR_Byte(0xb0 + y, OLED_CMD);
OLED_WR_Byte(((x & 0xf0) >> 4) | 0x10, OLED_CMD);
OLED_WR_Byte((x & 0x0f), OLED_CMD);
}
再解释 OLED_ShowChar,这里会用到oledfont.h(会统一打包到附件里),里面是已经做好了的各种常见字母数字符号的点阵序列,我们只需要找到需要的字母的索引即可。
/**
*@brief display a character
*@param x:0-127, y:0-7, chr: the character, sizey: the size of it, actually vertical size
*@retval None
*/
//在指定位置显示一个字符,包括部分字符
//x:0~127
//y:0~7
//sizey:选择字体 6x8 8x16
void OLED_ShowChar(uint8_t x, uint8_t y, uint8_t chr, uint8_t sizey)
{
uint8_t c = 0, sizex = sizey / 2;
uint16_t i = 0, size1;
if (sizey == 8)
size1 = 6;
else
size1 = (sizey / 8 + ((sizey % 8) ? 1 : 0)) * (sizey / 2);
c = chr - ' '; //得到偏移后的值
OLED_Set_Pos(x, y);
for (i = 0; i < size1; i++)
{
if (i % sizex == 0 && sizey != 8)
OLED_Set_Pos(x, y++);
if (sizey == 8)
OLED_WR_Byte(asc2_0806[c][i], OLED_DATA); //6X8字号
else if (sizey == 16)
OLED_WR_Byte(asc2_1608[c][i], OLED_DATA); //8x16字号
// else if(sizey==xx) OLED_WR_Byte(asc2_xxxx[c][i],OLED_DATA);//用户添加字号
else
return;
}
}
仍然在此鸣谢b站@m-RNA,我的工程文件大部分参考于他,他在b站有MSP432的快速入门视频和相应资料:MSP432P4电赛入门速成/Keil/CCS/VScode_哔哩哔哩_bilibili。
还有前文的参考资料也已经标明出处。
限于本人水平,肯定有很多疏漏,希望大家多多指教!