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;
- }