FM25L256与嵌入式linux之SPI通信程序

2019-07-13 00:47发布

/* * Driver_FlashParam.c * * Created on: 2017年5月27日 * Author: Administrator */ #ifndef LIB_DRI_FLASHPARAM #define LIB_DRI_FLASHPARAM #include "driver_includes.h" #endif #define DEV_PATH "/sys/class/gpio/gpio22/value" // 输入输出电平值设备 #define EXPORT_PATH "/sys/class/gpio/export" // GPIO设备导出设备 #define DIRECT_PATH "/sys/class/gpio/gpio22/direction" // GPIO输入输出控制设备 #define OUT "out" #define IN "in" #define GPIO "22" // GPIO1_22----CS引脚 #define HIGH_LEVEL "1" #define LOW_LEVEL "0" int FLASH_CS_FD_DEV; int FLASH_CS_FD_EXP; int FLASH_CS_FD_DIR; int FLASH_SPI_FD_DIR; static const char *device = "/dev/spidev0.0"; uint8_t SPI_MODE; uint8_t SPI_BITS; uint16_t SPI_SPEED; #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) //fm25L256 cmd #define FM_OPT_WREN 0x06//写允许 #define FM_OPT_WRDI 0x04//写操作不允许 #define FM_OPT_RDSR 0x05//读状态 #define FM_OPT_WRSR 0x01//写状态 #define FM_OPT_ERAD 0x03//读存储器数据 #define FM_OPT_WRIT 0x02//写存储器数据 #define FM_OPT_ADDR 0x0 static uint16_t gOptAddr = FM_OPT_ADDR; extern int ioctl (int __fd, unsigned long int __request, ...) __THROW;//这里是ioctl会有警告,是隐式声明的 static int spi_write_only(int fd, const uint8_t *wbuf, int wlen, uint8_t *rbuf, int rlen){ int ret = 0; usleep(5); Flash_CS_LOW(); usleep(5); Flash_CS_HIGH(); usleep(10); Flash_CS_LOW(); struct spi_ioc_transfer tr[1] = { { .tx_buf = (unsigned long)wbuf, .rx_buf = 0, .len = wlen, .speed_hz = 5000000, .delay_usecs = 0, .bits_per_word = 8, }, }; ret = ioctl(fd, SPI_IOC_MESSAGE(1), tr); usleep(5); Flash_CS_HIGH(); usleep(5); return ret; } static int spi_write_read(int fd, const uint8_t *wbuf, int wlen, uint8_t *rbuf, int rlen) { int ret = 0; usleep(5); Flash_CS_LOW(); usleep(5); Flash_CS_HIGH(); usleep(10); Flash_CS_LOW(); struct spi_ioc_transfer tr[2] = { { .tx_buf = (unsigned long)wbuf, .rx_buf = 0, .len = wlen, .speed_hz = 5000000, .delay_usecs = 0, .bits_per_word = 8, }, { .tx_buf = 0, .rx_buf = (unsigned long)rbuf, .len = rlen, .speed_hz = 5000000, .delay_usecs = 0, .bits_per_word = 8, }, }; ret = ioctl(fd, SPI_IOC_MESSAGE(2), tr); usleep(5); Flash_CS_HIGH(); usleep(5); return ret; } static void FRAM_Write8bits(uint8_t u8Data) { int ret; usleep(5); Flash_CS_LOW(); usleep(5); Flash_CS_HIGH(); usleep(10); Flash_CS_LOW(); uint8_t tx[] = {u8Data}; struct spi_ioc_transfer tr = { .tx_buf = (unsigned long)tx, //定义发送缓冲区指针 .rx_buf = 0, //定义接收缓冲区指针 .len = ARRAY_SIZE(tx), .delay_usecs = 0, .speed_hz = 5000000, .bits_per_word = 8, }; ret = ioctl(FLASH_SPI_FD_DIR, SPI_IOC_MESSAGE(1), &tr); if (ret < 0) printf("can't send spi message1 "); usleep(5); Flash_CS_HIGH(); usleep(5); } int Flash_CS_IO_Init(void) { int ret; FLASH_CS_FD_EXP = open(EXPORT_PATH, O_WRONLY); // 打开GPIO设备导出设备 if(FLASH_CS_FD_EXP < 0) { perror("open export:"); return -1; } write(FLASH_CS_FD_EXP, GPIO, strlen(GPIO)); FLASH_CS_FD_DIR = open(DIRECT_PATH, O_RDWR); if(FLASH_CS_FD_DIR < 0) { perror("open gpio dir:"); return -1; } ret = write(FLASH_CS_FD_DIR, OUT, strlen(OUT)); // 设置为输出模式 if(ret < 0) { close(FLASH_CS_FD_DIR); perror("write gpio dir:"); return -1; } FLASH_CS_FD_DEV = open(DEV_PATH, O_RDWR); // 先打开设备 if(FLASH_CS_FD_DEV < 0) { perror("open gpio value:"); close(FLASH_CS_FD_DEV); return -1; } return 0; } void Flash_CS_LOW(void)//低电平有效 { int ret; ret = write(FLASH_CS_FD_DEV,LOW_LEVEL,strlen(HIGH_LEVEL)); if(ret < 0) { perror("write gpio_cs low :"); } } void Flash_CS_HIGH(void) { int ret; ret = write(FLASH_CS_FD_DEV,HIGH_LEVEL,strlen(HIGH_LEVEL)); if(ret < 0) { perror("write gpio_cs high :"); } } void Flash_init(uint8_t mode,uint8_t bits,uint32_t speed) { int ret; Flash_CS_IO_Init(); FLASH_SPI_FD_DIR = open(device, O_RDWR); if (FLASH_SPI_FD_DIR < 0) { perror("can't open device"); } mode = SPI_MODE_0; ret = ioctl(FLASH_SPI_FD_DIR, SPI_IOC_WR_MODE,&mode);//设置模式 if(ret < 0) { perror("can't set mode"); } ret = ioctl(FLASH_SPI_FD_DIR, SPI_IOC_RD_MODE,&mode);//设置模式 if(ret < 0) { perror("can't set mode"); } ret = ioctl(FLASH_SPI_FD_DIR, SPI_IOC_WR_BITS_PER_WORD, &bits);//设置SPI每字的数据长度 if(ret < 0) { perror("can't set bits"); } ret = ioctl(FLASH_SPI_FD_DIR, SPI_IOC_RD_BITS_PER_WORD, &bits);//设置SPI每字的数据长度 if(ret < 0) { perror("can't set bits"); } ret = ioctl(FLASH_SPI_FD_DIR, SPI_IOC_WR_MAX_SPEED_HZ, &speed);//设置SPI最大总线速度 if (ret < 0) { perror("can't set max speed hz"); } ret = ioctl(FLASH_SPI_FD_DIR, SPI_IOC_RD_MAX_SPEED_HZ, &speed);//设置SPI最大总线速度 if (ret < 0) { perror("can't set max speed hz"); } SPI_MODE = mode; SPI_BITS = bits; SPI_SPEED = speed; printf("spi mode: %d ", mode); printf("bits per word: %d ", bits); printf("max speed: %d Hz (%d KHz) ", speed, speed/1000); } void Flash_Update_Thread(void) { int ret; int i; int tmpSize; uint8_t wrBuf[128]; uint8_t rdBuf[128]; int index; int optSize; wrBuf[0] = FM_OPT_WRSR; wrBuf[1] = 0; wrBuf[2] = 0; tmpSize = 128; while(1) { sleep(1); Flash_CS_LOW(); FRAM_Write8bits(FM_OPT_WREN); index = 0; wrBuf[index++] = FM_OPT_WRIT; wrBuf[index++] = (gOptAddr>>8)&0xff; wrBuf[index++] = (gOptAddr>>0)&0xff; srand((unsigned)time(NULL)); printf("write data = "); if(tmpSize){ for(i = 0; i < tmpSize; i++){ rdBuf[i] = 1 + rand()%100+1; printf("%02x ", rdBuf[i]); } } else{ tmpSize = 128; for(i = 0; i < tmpSize; i++){ rdBuf[i] = 0; printf("%02x ", rdBuf[i]); } } printf(" "); memcpy(&wrBuf[index], rdBuf,tmpSize); index += tmpSize; optSize = index; ret = spi_write_only(FLASH_SPI_FD_DIR, wrBuf,optSize, 0, 0); if(ret < 0) printf("write error,err = %d ", ret); else printf("write ok.ret = %d ", ret); memset(rdBuf, 0, sizeof(rdBuf)); FRAM_Write8bits(FM_OPT_WREN); FRAM_Write8bits(FM_OPT_ERAD);//这里十分重要,不然读取数据为全为0 index = 0; wrBuf[index++] = FM_OPT_ERAD; wrBuf[index++] = (gOptAddr>>8)&0xff; wrBuf[index++] = (gOptAddr>>0)&0xff; ret = spi_write_read(FLASH_SPI_FD_DIR, wrBuf, index, rdBuf, sizeof(rdBuf)); if(ret < 0){ printf("read error, err = %d ", ret); } else{ printf("read ok.ret = %d, data = ", ret); for(index = 0; index < sizeof(rdBuf); index++){ printf("%02x ", rdBuf[index]); } printf(" "); Flash_CS_HIGH(); } } }

具体数据手册请参考:http://pdf1.alldatasheet.com/datasheet-pdf/view/107175/ETC/FM25L256.html

演示结果为:

欢迎关注并加入物联网行业联盟,积累行业人脉和资源。