STM32 M0之SPI
从M3到M0,可能SPI的接口函数大致类似,但是细节略有不同
仔细观察寄存器描述,虽然个别存在差异,但是真心不知道竟然有太多的“玄机”
这次的问题主要出在了数据宽度上:
1. M3/M4的数据宽度支持8/16,是SPI_CR1中DFF: Data frame format控制的,实际使用中,只要我配置好数据宽度,直接操作DR寄存器即可。
2. M0的看起来更加强大,在SPI_CR2中DS [3:0]: Data size控制,支持4..16个bits的数据。
所以开始的时候我使用M3的操作方式,直接把驱动函数移了过来,下面为初始化代码
/*
*********************************************************************************************************
* Function Name: bsp_spi_init
* Description : SPI初始化
* Input : None
* Output : None
* Return : None
*********************************************************************************************************
*/
static void
bsp_spi_init(void)
{
SPI_InitTypeDef SPI_InitStructure; BSP_SPI_FRAM_CS(); /* SPI_CS初始化 */
SPI_StructInit(&SPI_InitStructure);
SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;
SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_LSB;
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2;
SPI_Init(BSP_SPI_FRAM, &SPI_InitStructure);
/** Enable the SPI */
SPI_Cmd(BSP_SPI_FRAM, ENABLE);
}
本以为这样就OK了,后来发现二者还是有区别的:
M3的话你直接写DR寄存器,会自动根据你的配置数据长度8/16发送数据
M0的话,你直接写DR寄存器,他不会根据你写的数据长度发送,依旧发送的是16bits
后来观察ST官方给的驱动代码:
M3的接口函数没有区分,都是直接操作DR
// M3的发送代码
/**
* @brief Transmits a Data through the SPIx/I2Sx peripheral.
* @param SPIx: where x can be
* - 1, 2 or 3 in SPI mode
* - 2 or 3 in I2S mode
* @param Data : Data to be transmitted.
* @retval None
*/
void SPI_I2S_SendData(SPI_TypeDef* SPIx, uint16_t Data)
{
/* Check the parameters */
assert_param(IS_SPI_ALL_PERIPH(SPIx)); /* Write in the DR register the data to be sent */
SPIx->DR = Data;
}
M0的官方代码比较复杂:
/**
* @brief Transmits a Data through the SPIx/I2Sx peripheral.
* @param SPIx: where x can be 1 or 2 in SPI mode to select the SPI peripheral.
* @param Data: Data to be transmitted.
* @retval None
*/
void SPI_SendData8(SPI_TypeDef* SPIx, uint8_t Data)
{
uint32_t spixbase = 0x00; /* Check the parameters */
assert_param(IS_SPI_ALL_PERIPH(SPIx)); spixbase = (uint32_t)SPIx;
spixbase += 0x0C; *(__IO uint8_t *) spixbase = Data;
} /**
* @brief Transmits a Data through the SPIx/I2Sx peripheral.
* @param SPIx: where x can be 1 or 2 in SPI mode or 1 in I2S mode to select
* the SPI peripheral.
* @param Data: Data to be transmitted.
* @retval None
*/
void SPI_I2S_SendData16(SPI_TypeDef* SPIx, uint16_t Data)
{
/* Check the parameters */
assert_param(IS_SPI_ALL_PERIPH(SPIx)); SPIx->DR = (uint16_t)Data;
}
虽然都是操作的DR,但是M0这里把DR强转成8bits宽度的指针,之后操作。
因为我只是发送8bits的数据,所以这样算是OK了
至于其他的非8/16的宽度如何操作,暂时就不去纠结了。。。。
我最后的做法简单粗暴,直接对DR强行转换:
(*((volatile unsigned char*)(&BSP_SPI_FRAM->DR) ))= dat;
这样免得调用他那个发送的库,各个平台的代码归档起来也方便一些。
至于这样设计的原因,我考虑还是M0的字节对齐问题吧?
STM32 M0之SPI的更多相关文章
- STM32学习笔记——SPI串行通讯(向原子哥学习)
一.SPI 简介 SPI是 Serial Peripheral interface 的缩写,就是串行外围设备接口.SPI 接口主要应用在 EEPROM, FLASH,实时时钟,AD 转换器,还有数 ...
- 怎样从Cortex-m向STM32移植使用SPI接口协议
/*************************************************************************************************** ...
- STM32—4线SPI驱动SSD1306 OLED
文章目录 一.OLED简介 二.驱动SSD1306所需知识 1.引脚介绍 2.通信时序 3.显存GRAM 4.字库 5.SSD1306基本命令 三.代码讲解 1.相关引脚配置 2.模拟SPI通信 3. ...
- STM32—SPI详解
目录 一.什么是SPI 二.SPI协议 物理层 协议层 1.通讯时序图 2.起始和停止信号 3.数据有效性 4.通讯模式 三.STM32中的SPI 简介 功能框图 1.通讯引脚 2.时钟控制逻辑 3. ...
- STM32的SPI口的DMA读写[原创www.cnblogs.com/helesheng]
SPI是我最常用的接口之一,连接管脚仅为4根:在常见的芯片间通信方式中,速度远优于UART.I2C等其他接口.STM32的SPI口的同步时钟最快可到PCLK的二分之一,单个字节或字的通信时间都在us以 ...
- [stm32] 一个简单的stm32vet6驱动的天马4线SPI-1.77寸LCD彩屏DEMO
书接上文<1.一个简单的nRF51822驱动的天马4线SPI-1.77寸LCD彩屏DEMO> 我们发现用16MHz晶振的nRF51822驱动1.77寸的spi速度达不到要求 本节主要采用7 ...
- 嵌入式单片机STM32应用技术(课本)
目录SAIU R20 1 6 第1页第1 章. 初识STM32..................................................................... ...
- SPI接口扫盲 SPI定义/SPI时序(CPHA CPOL)
SPI接口扫盲 douqingl@gmail.com 为何要写这篇文档?百度上找出来的SPI接口中文描述都说的太过简略,没有一篇文档能够详尽的将SPI介绍清楚的.wikipedia英文版[注释 ...
- 【转】spi测试自发自收(中断通信方式)
1.初始化spi时钟 void spiRccinit(void) { RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); RCC_APB2Peri ...
随机推荐
- 7、Spring Boot 2.x 集成 Redis
1.7 Spring Boot 2.x 集成 Redis 简介 继续上篇的MyBatis操作,详细介绍在Spring Boot中使用RedisCacheManager作为缓存管理器,集成业务于一体. ...
- CF46F Hercule Poirot Problem
题意: 有n个房间和m扇门,每扇门有且仅有一把钥匙 有k个人度过了两天,在第一天开始的时候所有的门都是关闭的,在第二天结束的时候,所有的门也都是关闭的 在这两天内,每个人可以执行如下操作若干次: 关上 ...
- loaction.reload(false)和location.reload(true)的区别
loaction.reload(false)和location.reload(true)有差别啊,一个是先判断页面有没修改,有的话就从服务器下载页面,没有就直接从缓存里拿(这个会提升响应性能)而把该方 ...
- 【线性代数】5-1:行列式性质(The Properties of Determinants)
title: [线性代数]5-1:行列式性质(The Properties of Determinants) categories: Mathematic Linear Algebra keyword ...
- Codeforces 1272 A-E
Codeforces 1272 A-E A Three Friends 直接枚举所有情况,共\(3\times 3\times 3=27\)种. code #include<bits/stdc+ ...
- pause函数
pause函数 调用该函数可以造成进程主动挂起,等待信号唤醒.调用该系统调用的进程将处于阻塞状态(主动放弃cpu) 直到有信号递达将其唤醒. int pause(void); 返回值:-1 并 ...
- Python3操作YAML文件
数据及配置文件之争 数据及文件通常有三种类型: 配置文件型:如ini,conf,properties文件,适合存储简单变量和配置项,最多支持两层,不适合存储多层嵌套数据 表格矩阵型:如csv,exce ...
- MySQL中使用LIMIT分页
需求:客户端通过传递pageNum(页码)和pageSize(每页显示的条数)两个参数去分页查询数据库表中的数据. 我们知道MySQL提供了分页函数limit m,n,但是该函数的用法和需求不一样,所 ...
- 微信小程序之简单记账本开发记录(三)
昨天已经编辑了主界面,在wxml文件中设置好跳转链接之后,就可以进行下一步的开发了 在pages中建立一个新的页面文件夹作为之后的支出页面 编辑后台,今天先搭建大致界面
- deepin安装下载,部署在虚拟机上
第一次接触linux就用了很久的Ubuntu,后来尝试了Manjaro.Debian,还是用了Ubuntu,但是用VM虚拟机使用的ubuntu经常卡顿.我始终觉得ubuntu的默认桌面环境gnome可 ...