本来要接着写滴答定时器的,但是趁热打铁写下SPI2到SPI1的移植。
为什么SPI2到SPI1的移植要放在nRF24L01模块里写呢,因为无线模块最重要的数据传输就是通过SPI实现的。为什么需要移植呢,因为即使是一个厂家的板子,不同型号之间它的无线模块引脚也有可能是不同的,顺便稿下移植,加深下理解。SPI2移植到SPI1呢,自己做的时候遇到了一些问题,就从遇到的问题顺便讲下初始化。
1.引脚问题
看stm32的手册,不知道为什么,无论在GPIO还是在SPI里都没有看到这个引脚的问题(初学者有可能移植的时候可能纳闷为什么是这些引脚),只有在引脚复用AFIO那里才提了一下,如下图
这样才知道SPI1的引脚,但是SPI2的引脚手册里没有提到,只能结合板子的电路原理图顺便查一下了,以我用的两个德飞莱的板子为例,前者是德飞莱M3S,可以插ILI9320那个板子,后者是德飞莱小一些没有SD插槽那个板子。
可以看到二者的引脚是不同的,但是引脚并不是随意给出的,在不进行重映射的情况下,前者的SPI引脚是SPI2对应的引脚,后者则是SPI1对应的引脚。由于对应的引脚不同,自然在GPIO的初始化时候,要修改初始化的引脚,引脚的输入输出模式,在数据手册中已经给出,如下
2.时钟的使能
由于引脚改了,使能的GPIO时钟也需要进行一下修改,同时切记不要忘了SPI1和SPI2时钟的区别,看一下数据手册中给出的系统结构,如下图
特别需要注意的是SPI1挂在APB2上,而SPI2和SPI3挂在APB1上,因此SPI时钟初始化的时候,要注意是
RCC_APB1PeriphClockCmd( RCC_APB1Periph_SPI2, ENABLE );
RCC_APB2PeriphClockCmd( RCC_APB2Periph_SPI1, ENABLE );
这两句的哪一个(我还傻傻滴找了半天RCC_APB1Periph_SPI1)
这个时钟在设置SPI速度的时候还会导致一个小问题,APB2的最大时钟是APB1的一倍,由于nRF24L01的最大频率是10MHz,因此移植的时候注意一下。
3.片选和使能的预定义
看一下上面的无线模块的电路原理图,除了SPI引脚就是片选CSN和使能CE引脚了,这两个引脚是用于开始和结束SPI通信的,移植的时候也有可能没注意到。
库函数中为了简洁明了,一般将引脚的置高置低都用预定义的形式表示,比如CE的置高置低是这么表示的
#define NRF24L01_CE_SET GPIO_SetBits(GPIOG,GPIO_Pin_6)
#define NRF24L01_CE_CLR GPIO_ResetBits(GPIOG,GPIO_Pin_6)
在移植的时候,这种预定义很容易忽略,忘了的话根本就不会开始SPI通信,自然也就没有现象了。
4.库函数的改变
在SPI2的函数中,只要是涉及写寄存器的部分,就要看下到底写的是SPI2还是SPI1的寄存器,当然,这里有一个很明显的特点,就是stm32官方的库函数一般是通用的,像下面这个SPI命令函数
SPI_Cmd(SPI_TypeDef* SPIx, FunctionalState NewState)
而厂商写的,一般都是需要注意下的,比如SPI速度设置的函数
void SPI2_SetSpeed(u8 SPI_BaudRatePrescaler)
{
assert_param(IS_SPI_BAUDRATE_PRESCALER(SPI_BaudRatePrescaler));
SPI2->CR1&=0XFFC7;
SPI2->CR1|=SPI_BaudRatePrescaler;
SPI_Cmd(SPI2,ENABLE);
}
这里写的寄存器就是SPI2的寄存器,移植的时候就需要改一下啦(结构体寄存器关系滴答定时器那里已经讲过啦)
5.玄学问题((*^__^*)。。。)
搞硬件,必不可少的会出现玄学问题,比如keil4好使,keil5不好使的什么的,所以需要不断地尝试,自己做这个移植的时候,有一段毫不相关引脚注释居然改变了结果,最后一句一句注释掉,发现实际是厂商的函数写的不规范,把端口的输入输出频率的初始化给漏掉了大部分玄学问题都是都原因的,移植的时候不断调试就能找到问题所在。
上一篇:STM32学习笔记---基于UCOSII的EXTI外部按键中断实验
下一篇:STM32F1x系列内存结构
推荐阅读最新更新时间:2024-03-16 16:15