论武天地论坛

 找回密码
 立即注册
搜索
查看: 6675|回复: 0

2.08-外设篇-SPI(RTOS 2.2.0)

[复制链接]

58

主题

58

帖子

244

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
244
发表于 2020-10-27 19:47:07 | 显示全部楼层 |阅读模式





SPI引脚
819239-20200301154551783-387223067.png




上程序
819239-20200301154313859-1703303933.png





#include "spi_interface.h"



SpiAttr spiConfig;//配置SPI
SpiData SpiSend;//配置SPI发送的数据




2.配置GPIO,设置为主机模式

819239-20200301154714326-932110444.png



3.关于发送数据
首先大家不要被官方规定的发送的几种数据所迷惑
819239-20200301155531084-1674564593.png



你要明白,无论是啥命令,地址,数据
都是用SPI发送数据而已
你要是这都不明白....说明你已经被协议弄糊涂了
其实对于通信而言你需要把大的方向搞明白
什么叫:通信方式 (SPI,串口)
什么叫:通信协议 (在通信方式基础上规定的数据协议)

之所以有命令,地址,和数据之分,其实是咱和某个支持SPI的芯片通信的时候
如果想读取SPI芯片某个寄存器里面的值
你需要先用SPI发送发送读命令(告诉芯片我要读数据)
然后用SPI发送要读取的地址
然后另一个芯片就返回过来数据了

3.发送一个字节数据
用cmd测试
819239-20200301163914110-1923211219.png



为了方便我监控数据,使用了一个1S的硬件定时器

819239-20200301163719563-479925458.png



        SpiSend.cmd= 0x55;//设置发送的数据         SpiSend.cmdLen=1;//发送的数据个数(字节为单位)
        SPIMasterSendData(SpiNum_HSPI,&SpiSend);//发送数据

监控如下
819239-20200301164110064-902506076.png





4.发送两个字节数据
819239-20200301164151616-1443075986.png



        SpiSend.cmd= 0x55aa;//设置发送的数据
        SpiSend.cmdLen=2;//发送的数据个数(字节为单位)
        SPIMasterSendData(SpiNum_HSPI,&SpiSend);//发送数据

测试如下
先传的0xaa  后传输的 0x55
用户实际应用的时候要注意!
819239-20200301164345890-1351931043.png














5.再看一下 addr
addr最大可以传输一个32位的数据(4字节)
819239-20200301164453115-388721630.png




5.1 注意下下面的情况
819239-20200301164841505-1201108634.png



测试如下:
注意:
其实实际上设置为传输1位的时候芯片内部默认先取addr数据地址的 低八位
uint32_t data = 0x01;
实际上 data = 0x01000000
传输数据的时候芯片先取的最后面的00
使用addr传输的1位数据的时候需要注意
819239-20200301165021311-511814925.png




注意:
注意:
注意:
使用 addr 只要是不传输4位数据
芯片内部都会默认先传低八位

使用 addr 无论是只要是不传输4位数据
芯片内部都会默认先传低八位

使用 addr 无论是只要是不传输4位数据
芯片内部都会默认先传低八位


下面看用addr传输4位数据

819239-20200301165332220-913267034.png


u32 cnt = 0;
uint32_t data = 0x0103070f;
void hw_test_timer_cb(void)
{
    cnt++;
    if(cnt>1000)//1S
    {
        cnt=0;
        SpiSend.addr= &data;//设置发送的数据
        SpiSend.addrLen=4;//发送的数据个数(字节为单位)
        SPIMasterSendData(SpiNum_HSPI,&SpiSend);//发送数据
    }
}


测试如下:
正好传输4位数据的时候,芯片内部默认先传输高八位
819239-20200301165606741-1300686312.png



5.2 传输一个u8型4字节的数组,传输个数是2字节
芯片默认是先传输数组后面的数据,依次向前
819239-20200301170938118-1793285471.png





u8 temp[4] = {0x01,0x02,0x03,0x04};
void hw_test_timer_cb(void)
{
    cnt++;
    if(cnt>1000)//1S
    {
        cnt=0;
        SpiSend.addr= (uint32_t *)(&temp);//设置发送的数据
        SpiSend.addrLen=2;//发送的数据个数(字节为单位)
        SPIMasterSendData(SpiNum_HSPI,&SpiSend);//发送数据
    }
}




819239-20200301171051525-861316817.png



5.3 传输一个u8型4字节的数组,如果传输个数是4字节
芯片也会先传输数组后面的数据,依次向前

819239-20200301170650380-1904260755.png



u8 temp[4] = {0x01,0x02,0x03,0x04};
void hw_test_timer_cb(void)
{
    cnt++;
    if(cnt>1000)//1S
    {
        cnt=0;
        SpiSend.addr= (uint32_t *)(&temp);//设置发送的数据
        SpiSend.addrLen=2;//发送的数据个数(字节为单位)
        SPIMasterSendData(SpiNum_HSPI,&SpiSend);//发送数据
    }
}








819239-20200301170715947-2065296372.png


以上为 使用addr 传输数据时需要注意的地方






6 现在看一下  data
只要记住一点即可
data 和 上面的 addr 传输的时候取数据的方式完全相反
data就不再多加测试:用户只需要记住上面的话即可!
由此便推导出使用data应该会怎么传输
我想官方这样做是为了应对客户不同的传输数据情况!

819239-20200301171242145-80366780.png




6.1 测试使用data ,u8型数组传输2字节的情况
819239-20200301171747419-158813493.png



u8 temp[4] = {0x01,0x02,0x03,0x04};
void hw_test_timer_cb(void)
{
    cnt++;
    if(cnt>1000)//1S
    {
        cnt=0;
        SpiSend.data= (uint32_t *)(&temp);//设置发送的数据
        SpiSend.dataLen=2;//发送的数据个数(字节为单位)
        SPIMasterSendData(SpiNum_HSPI,&SpiSend);//发送数据
    }
}


测试如下:
和addr完全相反,data是先传输数组前面的数据
819239-20200301171824802-370214337.png



6.2 测试使用data ,u8型数组传输4字节的情况
819239-20200301172028069-1910750626.png


u8 temp[4] = {0x01,0x02,0x03,0x04};
void hw_test_timer_cb(void)
{
    cnt++;
    if(cnt>1000)//1S
    {
        cnt=0;
        SpiSend.data= (uint32_t *)(&temp);//设置发送的数据
        SpiSend.dataLen=4;//发送的数据个数(字节为单位)
        SPIMasterSendData(SpiNum_HSPI,&SpiSend);//发送数据
    }
}


测试如下:
819239-20200301172127734-2118020411.png




关于组合起来
819239-20200301172313759-530155841.png





u32 cnt = 0;
u8 temp[4] = {0x01,0x02,0x03,0x04};
void hw_test_timer_cb(void)
{
    cnt++;
    if(cnt>1000)//1S
    {
        cnt=0;
        SpiSend.cmd = 0x55;
        SpiSend.cmdLen = 1;
        SpiSend.addr= (uint32_t *)(&temp);//设置发送的数据
        SpiSend.addrLen=4;//发送的数据个数(字节为单位)
        SPIMasterSendData(SpiNum_HSPI,&SpiSend);//发送数据
    }
}





测试如下:
总结:
cmd,addr,data的数据该怎么传还是怎么传
但是是先传 cmd 然后 addr 最后 data

819239-20200301172456016-1208554430.png



如果想SPI发送数据的时候接收数据


SPIMasterRecvData(SpiNum spiNum, SpiData* pOutData)

819239-20200301172656344-1210366175.png




史上最短的引脚模拟SPI
/*** @brief  SPI函数
* @param  value--发送的数据
* @param  None
* @param  None
* @retval SPI接收的数据
* @example
**/
unsigned char SPIWriteRead(unsigned char value)
{
    unsigned char i=0,temp=0;
    SPI_CLK = 0;//进入之前其实是高电平
    if(SPI_MISO)temp|=0x80;//接收数据
    for(i=0;i<8;i++)
    {
        SPI_MOSI=value&(0x80>>i);//准备数据
        SPI_CLK=1;
        SPI_CLK = 0;
        if(i<7)if(SPI_MISO)temp|=0x80>>(i+1);//接收数据
    }
    return temp;
}



源码在默认最大是20M
按照规律修改为其它频率
819239-20200322003251167-233124957.png



typedef enum
{
    SpiSpeed_2MHz  = 40 - 1,
    SpiSpeed_5MHz  = 16 - 1,
    SpiSpeed_10MHz = 8 - 1,
    SpiSpeed_16MHz = 5 - 1,
    SpiSpeed_20MHz = 4 - 1,
    SpiSpeed_40MHz = 2 - 1,
    SpiSpeed_80MHz = 1 - 1,
} SpiSpeed;




NONOS_SDK版本区别
#include "driver/spi_interface.h"

819239-20200322002945480-772694760.png



/*配置SPI GPIO 口*/
    WRITE_PERI_REG(PERIPHS_IO_MUX, 0x105);
    PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDI_U, 2);
    PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U, 2);
    PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTCK_U, 2);
    PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTMS_U, 2);


    /*配置SPI 模式*/
    spiConfig.mode = SpiMode_Master;//主机
    spiConfig.speed = SpiSpeed_20MHz;//时钟频率
    spiConfig.subMode = SpiSubMode_0;//模式0
    spiConfig.bitOrder = SpiBitOrder_MSBFirst;//先传输高位


    SpiSend.addr=0;
    SpiSend.addrLen=0;
    SpiSend.cmd=0;
    SpiSend.cmdLen=0;
    SPIInit(SpiNum_HSPI,&spiConfig);//初始化SPI



其它频率
819239-20200322003026469-416596025.png





typedef enum
{
    SpiSpeed_0_5MHz     = 160,
    SpiSpeed_1MHz       = 80,
    SpiSpeed_2MHz       = 40,
    SpiSpeed_5MHz       = 16,
    SpiSpeed_8MHz       = 10,
    SpiSpeed_10MHz      = 8,
    SpiSpeed_20MHz      = 4,
    SpiSpeed_40MHz      = 2,
    SpiSpeed_80MHz      = 1,

} SpiSpeed;




copycode.gif
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|论武天地论坛

GMT+8, 2024-3-29 15:47 , Processed in 0.076397 second(s), 21 queries .

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表