FreeRTOS SPI 时序以及模拟SPI时序

SPI(Serial Peripheral Interface),顾名思义就是串行外围设备接口。SPI,是一种高速的全双工同步的通信总线,并且在芯片的管脚上只占用四根线(MISO, MOSI, CLK, CS)可以不用CS片选引脚也是三线式,SPI有时候可以不用MISO, MOSI,中的一个,但CLK的引脚一定需要存在。SPI节约了芯片的管脚,同时为PCB的布局上节省空间,提供方便,正是出于这种简单易用的特性,现在越来越多的芯片集成了这种通信协议。

Motorola公司推出的三线同步接口,同步串行3线方式进行通信:一条时钟线SCK,一条数据输入线MOSI,一条数据输出线MISO(不存在片选引脚);用于 CPU与各种外围器件进行全双工、同步串行通讯

SPI存在四种工作模式分别由POL(极性)与PHA(相位)决定。
POL = 0(CLK时钟的空闲电平为低电平)
POL = 1(CLK时钟的空闲电平为高电平)
PHA = 0(CLK时钟下第一个跳变沿进行数据采集
PHA = 1(CLK时钟下第二个跳边沿进行数据采集
以下是SPI四种传输模式第一种与第三种使用广泛。
如下图所示:
SPI四种传输模式SPI内部结构
主机与从机共用同一个时钟,达到同步的目的。
SPI内部结构SPI编程实现

struct spi_config_data {
    unsigned int id;        /* SPI 控制器 ID */
    unsigned int cs_pin;    /* 指定作为 cs 脚的 GPIO */
    char *name;             /* name 仅作为一个标识 */
    unsigned int clk_rate;  /* 时钟频率(默认为 1*1000*1000) */

    enum spi_cs_valid_level cs_valid_level; /* 有效电平 */

    /* 数据传输的大小端模式选择,具体可选类型为 spi_data_endian 所定义的类型 */
    enum spi_data_endian tx_endian;
    enum spi_data_endian rx_endian;

    /* bits_per_word 代表数据的位宽.
        例如:bits_per_word = 32 时,SPI传输过程中的最小数据单位为32bit. */
    unsigned int bits_per_word;

    /**
     * 极性 spi_pol :
     * 当spi_pol=0,在时钟空闲即无数据传输时,clk电平为低电平
     * 当spi_pol=1,在时钟空闲即无数据传输时,clk电平为高电平
     * 相位 spi_pha :
     * 当spi_pha=0,表示在第一个跳变沿开始采集数据
     * 当spi_pha=1,表示在第二个跳变沿开始采集数据
     */
    unsigned int spi_pol;
    unsigned int spi_pha;

    unsigned int loop_mode; /* 循环模式,可用于测试 */
};

struct spi_device {
    struct spi_config_data config;
    struct list_head spi_drv_node;
};

/*获取时钟,初始化对应的IO口
*/
void soc_spi_init_driver(void);
/*初始化片选引脚,并将设备添加到链表中
*/
void soc_spi_register(struct spi_config_data *config);
/*传输msg
*/
void soc_spi_transfer(struct spi_device *spi, struct spi_message *msg, int count);
/*释放IO口,删除对应的节点
*/
void soc_spi_unregister(struct spi_device *spi);

其实spi传输数据,并不是只传输8,18,32位,这种特殊位的数据。优秀的应该做到2~32可调,并以 8, 16, 32位对齐。少于的都属于无效位。
以模拟gpio spi为例(以下是我个人以为比较有好的代码)
接口框架以上边相同(统一接口)

/*读采集通过传char数据,然后直接读取数据。
*/
unsigned int read_sample(const unsigned char *value, int bytes_per_sample);
/*写采集
*/
void write_sample(const unsigned char *rx_buf, int bytes_per_sample, unsigned int value);
/*读写采集
*/
unsigned int spi_write_read_sample(struct spi_gpio_config_data *config, int bits, unsigned int value);
/*spi传输协议每次之传输一个bit
*/
int spi_write_read_bit(struct spi_gpio_config_data *config, int bit);

static unsigned int spi_write_read_sample(struct spi_gpio_config_data *config, int bits, unsigned int value)
{
	int bit;
    int end = 0;
    int delta = -1;
    int start = bits;
    int i = start;
    unsigned int ret = 0;

    while (1) {
        bit = spi_write_read_bit(config, value & (1 << i));

        if (bit)
            ret |= (1 << i);
        i += delta;
		
        if (i == end)
            break;
    }

    return ret;
}

今天用错一个互斥锁,在注册spi设备时,用互斥锁进行保护设备节点添加到全局链表。不过多个spi所用的互斥锁并不是同一把锁,所以会导致第二把锁不能正常上锁。
解决方法
1、每个spi都定义一个自己的链表
2、用同一把锁进行上锁
3、使用临界区

#打卡第二天#有需要的可以联系博主QQ:1667869702

S32K144是封装了32位ARM Cortex-M4内核的微控制器系列,可以用于汽车和工业控制等领域。FreeRTOS是一种流行的开源实时操作系统,用于管理任务和资源,并提供通信和同步机制。SPI是一种全双工的串行通信接口,通常用于连接微控制器和外部设备,例如传感器、存储器和显示器等。在S32K144微控制器上,可以使用FreeRTOSSPI接口来实现各种应用。 首先,为使用SPI接口,需要配置SPI控制器和外设。这包括设置SPI时钟、数据传输速率、数据格式和通信模式等。通常使用SPI驱动程序来简化此过程,并确保与外设的正确通信。启用FreeRTOS后,可以创建多个任务来运行不同的操作,例如发送和接收数据,同时保持对更高级别任务的响应。可以使用FreeRTOS提供的信号量和队列等机制来实现任务间同步和互斥访问。 例如,S32K144可以使用FreeRTOSSPI接口来实现温度传感器读取。该功能涉及读取外设中的温度,并将其传输到主机控制器中。使用FreeRTOS,可以创建两个任务,一个用于读取温度传感器并将结果发送到队列中,另一个用于从队列中接收数据并将其格式化为可读的温度值并输出到串行通信接口。SPI驱动程序可确保与温度传感器的正确通信。 总之,S32K144和FreeRTOS可以结合使用SPI接口以实现各种应用,从而简化操作、提高效率和减少错误。但在使用此技术时,需了解SPIFreeRTOS的基础知识,并了解如何正确配置和管理它们。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值