![201a68e869e1563735e633fbf68190e4.png](https://i-blog.csdnimg.cn/blog_migrate/2c0b2d574cdb41b8a99748d86fafe72a.jpeg)
来源:百问网_嵌入式Linux wiki_jz2440 新1期视频维基教程 (视频文字版)
作者:韦东山
本文字数:1730,阅读时长:2分钟
前面我们都是通过GPIO管脚来实现的SPI通信,这节我们使用2440里面的GPIO控制器来实现SPI通信。
前面使用GPIO发送数据时,是手工的控制时钟线、数据线,我们使用SPI控制器的话,只需要 把数据写入寄存器,它就可以帮我自动那些时钟线和数据线,我们继续在上一节的基础上修改,添加一个文件s3c2440_spi.c和s3c2440_spi.h,同时修改Makefile,替换gpio_spi.c为s3c2440_spi.o。
从初始化函数开始,需要管脚初始化和SPI控制器初始化:
void SPIInit(void){ /* 初始化引脚 */ SPI_GPIO_Init(); SPIControllerInit();}
管脚初始化即需要把SPI相关的CLK、MOSI、MISO配置为对应的功能引脚:
static void SPI_GPIO_Init(void){ /* GPF1 OLED_CSn output */ GPFCON &= ~(3<
然后是SPI控制器的初始化,控制器的初始化可以参考芯片手册介绍的编程步骤:
![3886ce1c73f54882d0df82bbf53bd768.png](https://i-blog.csdnimg.cn/blog_migrate/ef67425a83b98821ed30de76194344e0.jpeg)
首先是设置波特率,要根据外设所能接受的范围来设置,比如查阅OLED的芯片手册得知其时钟最小值为100ns,即最小为10MHz;Flash时钟支持最大104MHz,为了代码简单,就直接取10MHz,根据等式推出寄存器值:
Baud rate = PCLK / 2 / (Prescaler value + 1)10 = 50 / 2 / (Prescaler value + 1)Prescaler value = 1.5 = 2
实际的波特率为:50/2/3=8.3MHz
根据参考流程,接下来设置SPI控制寄存器:
![e8c26a124de6ef7e8d441e6b88734e3c.png](https://i-blog.csdnimg.cn/blog_migrate/70ffd2e260573f875f3a3f275de55f32.jpeg)
[6:5]设置为查询模式: 00 polling mode[4]设置时钟使能: 1 = enable [3]设置为主机模式: 1 = master[2]设置无数据时时钟为低电平: 0[1]设置工作模式为模式A: 0 = format A[0]设置发送数据时无需读取数据: 0 = normal mode
static void SPIControllerInit(void){ /* OLED : 100ns, 10MHz * FLASH : 104MHz * 取10MHz * 10 = 50 / 2 / (Prescaler value + 1) * Prescaler value = 1.5 = 2 * Baud rate = 50/2/3=8.3MHz */ SPPRE0 = 2; SPPRE1 = 2; /* [6:5] : 00, polling mode * [4] : 1 = enable * [3] : 1 = master * [2] : 0 * [1] : 0 = format A * [0] : 0 = normal mode */ SPCON0 = (1<<4) | (1<<3); SPCON1 = (1<<4) | (1<<3); }
发送数据时,先检查状态寄存器,判断发送/接收数据是否准备好了,准备好后就把数据放在寄存器SPTDAT1里,SPI控制器就自己控制时序把数据自动发送出去了。
void SPISendByte(unsigned char val){ while (!(SPSTA1 & 1)); SPTDAT1 = val; }
接收数据时,先写0xFF到寄存器SPTDAT1,再检查状态寄存器,判断发送/接收数据是否准备好了,准备好后就读取寄存器SPTDAT1,读取出来的就是接收到的数据。
unsigned char SPIRecvByte(void){ SPTDAT1 = 0xff; while (!(SPSTA1 & 1)); return SPRDAT1; }
「新品首发」STM32MP157开发板火爆预售!首批仅300套