gpio模拟spi读写寄存器示例代码

gpio模拟spi通信示例代码(海思HI3531DV200平台)

读的时候,写1个32位的地址,读1个32位的数据,地址的最高位是1 
写的时候,一个32位的地址,一个32位的数据,地址的最高位是0
收发顺序:高字节先

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>

#define NCS      18                     //定义SS所对应的GPIO接口编号
#define SCLK     21                     //定义SCLK所对应的GPIO接口编号
#define MOSI     19                     //定义SCLK所对应的GPIO接口编号
#define MISO     20                    //定义MISO所对应的GPIO接口编号

#define  set_gpio_value gpio_set_value                                                                                          
#define  get_gpio_value gpio_get_value                                                                                             

static int gpio_set_value(int pin, int value)
{
    char cmd[128] = "";
    int fd = -1;
    sprintf(cmd, "/sys/class/gpio/gpio%d/value", pin);
    fd = open(cmd, O_RDWR);
    if(fd < 0)
    {
        printf("open gpio%d value fail\n", pin);
        return -1;
    }
    if(value)
    {
        write(fd, "1", strlen("1"));
    }
    else
    {
        write(fd, "0", strlen("0"));
    }

    close(fd);

    return 0;
}

static int gpio_get_value(int pin)
{
        char cmd[128] = "";
        int fd = -1;
        char value = 0;
        sprintf(cmd, "/sys/class/gpio/gpio%d/value", pin);
        fd = open(cmd, O_RDWR);
        if(fd < 0)
        {
                printf("open gpio%d value fail\n", pin);
                return -1;
        }

        read(fd, &value, 1);
        close(fd);

        if(value=='1')
        {
                return 1;
        }else
        {
                return 0;
        }
}          

static int gpio_direction_output(int pin, int value)                                                                                                           
{
        char cmd[128] = "";
        int fd = -1;
        sprintf(cmd, "/sys/class/gpio/gpio%d/direction", pin);
        fd = open(cmd, O_RDWR);
        if(fd < 0)
        {
                printf("open gpio%d value fail\n", pin);
                return -1;
        }
        write(fd, "out", strlen("out"));
        close(fd);

        memset(cmd, 0, sizeof(cmd));
        sprintf(cmd, "/sys/class/gpio/gpio%d/value", pin);
        fd = open(cmd, O_RDWR);
        if(fd < 0)
        {
                printf("open gpio%d value fail\n", pin);
                return -1;
        }
        if(value)
        {
                write(fd, "1", strlen("1"));
        }
        else
        {
                write(fd, "0", strlen("0"));
        }

        close(fd);

        return 0;
}

static int gpio_direction_input(int pin)
{
        char cmd[128] = "";
        int fd = -1;
        sprintf(cmd, "/sys/class/gpio/gpio%d/direction", pin);
        fd = open(cmd, O_RDWR);
        if(fd < 0)
        {
                printf("open gpio%d value fail\n", pin);
                return -1;
        }
        write(fd, "in", strlen("in"));
        close(fd);
}

static int udelay(int usec)
{
        return 0;
}

static int spi_request_gpio(void)                                                                                                      
{                                                                                                                                      
}
/* SPI端口初始化 */                                                                                                                    
static void spi_init(void)
{
    gpio_direction_output(NCS, 1);
    gpio_direction_output(SCLK, 0);
    gpio_direction_output(MOSI, 0);
    gpio_direction_input(MISO);
    set_gpio_value(SCLK, 0);
    set_gpio_value(MOSI, 0);
}

/*
从设备使能
enable:为1时,使能信号有效,SS低电平
为0时,使能信号无效,SS高电平                                                                                                  
*/                                                                                                                                     
void ss_enable(int enable)
{
    if (enable)
        set_gpio_value(NCS, 0);                  //SS低电平,从设备使能有效
    else
        set_gpio_value(NCS, 1);                  //SS高电平,从设备使能无效
}

/* SPI字节写 */
void spi_write_byte(unsigned char b)
{
    int i;
    for (i=7; i>=0; i--) {
        set_gpio_value(SCLK, 0);
        set_gpio_value(MOSI, b&(1<<i));         //从高位7到低位0进行串行写入
        set_gpio_value(SCLK, 1);                // CPHA=1,在时钟的第一个跳变沿采样
    }                                                                                                                                  
    set_gpio_value(SCLK, 0);
}


/* SPI字节读 */                                                                                                                        
unsigned char spi_read_byte(void)
{
    int i;
    unsigned int r = 0;
    for (i=0; i<8; i++) {
        set_gpio_value(SCLK, 0);
        set_gpio_value(SCLK, 1);                // CPHA=1,在时钟的第一个跳变沿采样
        r = (r<<1) | get_gpio_value(MISO);         //从高位7到低位0进行串行读出
    }
    set_gpio_value(SCLK, 0);
    return r;
}

/*
SPI读操作
buf:写缓冲区
len:写入字节的长度
*/
void spi_write (unsigned char* buf, int len)
{
    int i;
    /* SPI端口初始化 */
    spi_init();
    ss_enable(1);                       //从设备使能有效,通信开始
    //写入数据
    for (i=0; i<len; i++)
       spi_write_byte(buf[i]);
    ss_enable(0);

#if 0
    for (i=0; i<len; i++)
    {
        printf("buf[%d]=0x%02x\n", i, buf[i]);
    }
#endif
}


/*                                                                                                                                     
SPI读操作
buf:读缓冲区
len:读入字节的长度
*/
int spi_read(unsigned char* buf, int len)
{
    int value = 0;
    int i;
#if 0
    for (i=0; i<len; i++)
    {
        printf("buf[%d]=0x%02x\n", i, buf[i]);
    }
#endif
    /* SPI端口初始化 */
    spi_init();
    ss_enable(1);//从设备使能有效,通信开始
    //写入数据
    for (i=0; i<len; i++)
       spi_write_byte(buf[i]);
    //读入数据
    for (i=0; i<len; i++)
        buf[i] = spi_read_byte();
    ss_enable(0);//从设备使能无效,通信结束
#if 0
    for (i=0; i<len; i++)
    {
        value |= (buf[i]<<((len-1-i)*8));
        printf("recv buf[%d]=0x%02x\n", i, buf[i]&0xff);
    }
#endif
    return value;
}

#include <stdlib.h>

#define strToHex(strBuf) strtoul(strBuf, NULL, 16)
#define strToDec(strBuf) strtoul(strBuf, NULL, 10)

int str_to_int(char *buf)
{
    if(('0'== buf[0])&&('x'== buf[1] || 'X'== buf[1]))
        return(strToHex(buf));
    else
        return(strToDec(buf));
}


//读的时候,写1个32位的地址,读1个32位的数据,地址的最高位是1 
//写的时候,一个32位的地址,一个32位的数据,地址的最高位是0
//收发顺序:高字节先
int main(int argc, char **argv)
{
    char buf[8] = {};
    int addr = 0;
    int value = 0;

    if(argc==2)
    {
        addr = str_to_int(argv[1]);
        buf[0] = (addr>>24)&0xff;
        buf[0] |= (1<<7); //最高位为1表示读操作
        buf[1] = (addr>>16)&0xff;
        buf[2] = (addr>>8)&0xff;
        buf[3] = addr&0xff;
            value = spi_read(buf, 4);
        printf("spi read addr:0x%08x, value:0x%08x\n", addr, value);
    }else if(argc==3)
    {
        addr = str_to_int(argv[1]);
        value = str_to_int(argv[2]);
        buf[0] = (addr>>24)&0xff;
        buf[0] &= ~(1<<7); //最高位为0表示读操作
        buf[1] = (addr>>16)&0xff;
        buf[2] = (addr>>8)&0xff;
        buf[3] = addr&0xff;
        buf[4] = (value>>24)&0xff;
        buf[5] = (value>>16)&0xff;
        buf[6] = (value>>8)&0xff;
        buf[7] = value&0xff;
        spi_write(buf, 8);
        printf("spi write addr:0x%08x, value:0x%08x\n", addr, value);
    }else
    {
        printf("usage:\r\n./gpiospi 0x12345678(read)\r\n./gpiospi 0x12345678 0x87654321(write)\r\n");
    }

    return 0;
}  
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
GPIO模拟SPI是一种在树莓派或其他单片机中使用通用输入输出引脚来模拟SPI(串行外围设备接口)通信协议的方法。SPI是一种常用的串行通信协议,可以用于与各种外围设备(如传感器、显示屏、存储器等)进行数据交互。 要在树莓派中实现GPIO模拟SPI通信,首先需要通过软件创建SPI协议所需的时序。树莓派的GPIO引脚可以通过编程来实现读写操作,因此可以利用这些引脚来模拟SPI的时序。 具体实现步骤如下: 1. 首先,需要设置SPI引脚的模式,并确定引脚的输入输出方向。 2. 然后,可以通过编程实现SPI通信的时序,包括将数据发送给目标设备、接收目标设备返回的数据等。 3. 当需要发送数据时,可以将数据分别写入每个GPIO引脚,根据SPI协议,一般包括时钟线、数据线(MOSI)、数据输出线(MISO)和片选线(CS)。 4. 同样地,当需要接收数据时,可以通过读取GPIO引脚上的电平来获取目标设备返回的数据。 5. 在整个通信过程中,需要根据SPI协议规定的时序进行数据的发送和接收,以确保数据的正确传输。 需要注意的是,使用GPIO模拟SPI通信可能会面临一些性能上的限制,因为GPIO引脚的速度相对较慢。同时,在实际应用中,也要考虑到引脚的数目、通信距离等因素,以确保通信的可靠性和稳定性。 总的来说,通过GPIO模拟SPI通信可以在硬件资源有限的情况下实现与外围设备的串行数据交互,为嵌入式系统的开发提供了一种简单而经济的选择。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

悠哉无忧

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值