STM32MP157 | SPI总线

1.spi总线

1.1spi简介

1> SPI接口是Motorola 首先提出的全双工同步串行外围接口,

2> 采用主从模式(Master Slave)架构, 支持多slave模式应用,一般仅支持单Master。

3> 时钟由Master控制,在时钟移位脉冲下,数据按位传输,高位在前,低位在后(MSB first);

4> SPI接口有2根单向数据线,为全双工通信,目前应用中的数据速率可达几Mbps的水平。

5> SPI总线被广泛地使用在FLASH、ADC、LCD等设备与MCU间,要求通讯速率较高的场合。

在这里插入图片描述

2. SPI总线的硬件连接

SPI接口共有4根信号线,分别是:

​ 1> 设备选择线(从设备的选择线:通过片选线决定主机和哪个从机进行通信的):

​ NCS NSS /CS /SS(引脚的名字上边有一个横杠表示低电平有效)

​ 2> 时钟线 : CLK SCLK SCK SCL

​ 3> 串行输出数据线 : MOSI

​ 4> 串行输入数据线 : MISO

​ M : Master S : Slave I : Input O : Output

• (1)MOSI:主器件数据输出,从器件数据输入

• (2)MISO:主器件数据输入,从器件数据输出

• (3)SCLK :时钟信号,由主器件产生

• (4)/SS:从器件使能信号,由主器件控制(片选)

3. spi时序解析

在这里插入图片描述

​ 1> 起始信号 : NSS信号线由高变低,是SPI通讯的起始信号

​ 2> 结束信号 : NSS信号线由低变高,是SPI通讯的停止信号

​ 3> 数据传输:SPI使用MOSI及MISO信号线来传输数据,使用SCK信号线进行数据同步。MOSI及MISO数据线在SCK的每个时钟周期传输一位数据,且数据输入输出是同时进行的。SPI每次数据传输可以 8 位或 16 位为单位,每次传输的单位数不受限制。

​ 4> 数据传输:在时钟的上升沿期间,主机向MOSI数据线上写入数据,同时从机向MISO上写入数据;

在时钟的下降沿期间,主机从MISO数据线上读取数据,同时从机从MOSI线上读取数据。

1> 在SPI操作中,最重要的两项设置就是时钟极性(CPOL)和时钟相位(CPHA)这两项即是主从设备间数据采样的约定方式。

2> 时钟极性CPOL : 设置时钟空闲时的电平

​ 当CPOL = 0 ,SCK引脚在空闲状态保持低电平;

​ 当CPOL = 1 ,SCK引脚在空闲状态保持高电平。

3> **时钟相位CPHA :**设置数据采样时的时钟沿

​ 当 CPHA=0 时,MOSI或 MISO 数据线上的信号将会在 SCK时钟线的奇数边沿被采样

​ 当 CPHA=1时, MOSI或 MISO 数据线上的信号将会在 SCK时钟线的偶数边沿被采样

在这里插入图片描述

在这里插入图片描述

	SPI总线有四种通信的模式,具体使用那种通信模式进行通信,需要通信的双方约定一个通信模式。

在这里插入图片描述

4. spi驱动框架

在这里插入图片描述

配置spi核心层和spi控制器驱动到内核中

spi控制器驱动配置:

Device Drivers —>

  [*] SPI support  ---> 
		<*>   STMicroelectronics STM32 SPI controller      

spi核心层配置:

CONFIG_SPI_MASTER=y  

重新编译内核

make uImage LOADADDR=0xc2000000

将编译好的内核拷贝到tftpboot目录下

5.spi设备驱动的API

1.分配并初始化对象
	struct spi_driver {
		int			(*probe)(struct spi_device *spi);
		int			(*remove)(struct spi_device *spi);
		struct device_driver	driver;
	};
	struct device_driver {
		const char	*name;
        const struct of_device_id	*of_match_table;
    }
2.注册	
    #define spi_register_driver(driver) \
	__spi_register_driver(THIS_MODULE, driver)
3.注销
     void spi_unregister_driver(struct spi_driver *sdrv)
4.一键注册的宏
    module_spi_driver(结构体变量名);

6.spi驱动框架

#include <linux/init.h>
#include <linux/module.h>
#include <linux/spi/spi.h>
int myspi_probe(struct spi_device* spi)
{
    printk("%s:%d\n", __func__, __LINE__);
    return 0;
}
int myspi_remove(struct spi_device* spi)
{
    printk("%s:%d\n", __func__, __LINE__);
    return 0;
}
struct of_device_id oftable[] = {
    {.compatible = "st,myspi",},
    {}
};
MODULE_DEVICE_TABLE(of,oftable);

struct spi_driver myspi = {
    .probe = myspi_probe,
    .remove = myspi_remove,
    .driver = {
        .name = "hello",
        .of_match_table = oftable,
    },
};

module_spi_driver(myspi);
MODULE_LICENSE("GPL");

7. spi控制器设备树

stm32mp151.dtsi

spi4: spi@44005000 {
    #address-cells = <1>; 
    #size-cells = <0>; 
    compatible = "st,stm32h7-spi";                                                         
    reg = <0x44005000 0x400>;
    interrupts = <GIC_SPI 84 IRQ_TYPE_LEVEL_HIGH>;
    clocks = <&rcc SPI4_K>;
    resets = <&rcc SPI4_R>;
    dmas = <&dmamux1 83 0x400 0x01>,
           <&dmamux1 84 0x400 0x01>;
    dma-names = "rx", "tx";
    power-domains = <&pd_core>;
    status = "disabled";
};

7.1参考内核帮助文档编写自己的设备树

&spi4{
    pinctrl-names = "default", "sleep";
    pinctrl-0 = <&spi4_pins_b>;
    pinctrl-1 = <&spi4_sleep_pins_b>;
    cs-gpios = <&gpioe 11 0>;
    status = "okay";
    
    m74hc595@0{
        compatible = "st,myspi";
        reg = <0>;
        spi-max-frequency = <10000000>; //10Mhz
    };
};

8.spi相关的结构体及函数

int spi_write(struct spi_device *spi, const void *buf, size_t len) //发数据
int spi_read(struct spi_device *spi, void *buf, size_t len)       //接收数据
int spi_write_then_read(struct spi_device *spi,                   //同时收发
		const void *txbuf, unsigned n_tx,
		void *rxbuf, unsigned n_rx);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值