SPI で EEPROM を接続
使用するデバイスは、以前に Raspberry Pi Pico との接続を試した ROHM 社製 EEPROM BR25L320 デバイスです. (下の写真はピッチ変換基板に実装した状態です)ハードウェア接続
Longan Nano と EEPROM 間の接続は、SPI の 4端子(CS / SCLK / MOSI / MISO) と電源・GND 端子、書込み制御用の WP, HOLD の計 8本になります.SPI は Longan Nano の B12 ~ B15 端子(SPI1)を利用し、 WP, HOLD は GPIO A11 と A12 を接続しています.ソフトウェア
Platform IO IDE で作成したプロジェクトの main.c に SPI 周りの関数を追加します.main() 内で定期的に上記関数を呼んで EEPROM にアクセスしデータを書き込み&読み込みを行ない、LCD に表示しています./* SPI 初期設定 */ void longan_spi_eeprom_init() { int ret = 0; uint8_t buf[20]; /******** WP, HOLD pin setting ********/ rcu_periph_clock_enable(RCU_GPIOA); gpio_init(GPIOA, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_12); gpio_init(GPIOA, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_11); GPIO_BC(GPIOA) = GPIO_PIN_11; // WP (GPIO) = L GPIO_BC(GPIOA) = GPIO_PIN_12; // HOLD (GPIO) = L /******** SPI1 pin setting ********/ rcu_periph_clock_enable( RCU_GPIOB ); // GPIOB clock rcu_periph_clock_enable( RCU_AF ); // Alternate Functions clock rcu_periph_clock_enable( RCU_SPI1 ); // SPI1 clock // SPI1 GPIO pin configuration gpio_init(GPIOB, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_12); gpio_init(GPIOB, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_13); gpio_init(GPIOB, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_14); gpio_init(GPIOB, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_15); GPIO_BOP(GPIOB) = GPIO_PIN_12; // CS (GPIO) = H spi_parameter_struct spi_conf = { .trans_mode = SPI_TRANSMODE_FULLDUPLEX, .device_mode = SPI_MASTER, .frame_size = SPI_FRAMESIZE_8BIT, .clock_polarity_phase = SPI_CK_PL_LOW_PH_1EDGE, // MODE0 .nss = SPI_NSS_SOFT, .prescale = SPI_PSC_128, // ABP2=100MHz -> SPI0 ~0.8MHz .endian = SPI_ENDIAN_MSB }; spi_init(SPI1, &spi_conf); spi_enable(SPI1); if (spi_i2s_flag_get(SPI1, SPI_FLAG_CONFERR) == SET) { snprintf(buf, 50, "Init error : %d", ret); LCD_ShowString( 5, 5, buf, GREEN ); } else { snprintf(buf, 50, "Init OK : %d", ret); LCD_ShowString( 5, 5, buf, GREEN ); } } /* WP 端子制御 */ void spi_eep_wp_low() { GPIO_BC(GPIOA) = GPIO_PIN_11; // WP (GPIO) = L } void spi_eep_wp_high() { GPIO_BOP(GPIOA) = GPIO_PIN_11; // WP (GPIO) = H } /* HOLD 端子制御 */ void spi_eep_hold_low() { GPIO_BC(GPIOA) = GPIO_PIN_12; // HOLD (GPIO) = L } void spi_eep_hold_high() { GPIO_BOP(GPIOA) = GPIO_PIN_12; // HOLD (GPIO) = H } /* CS 端子制御 */ void spi_eep_cs_low() { GPIO_BC(GPIOB) = GPIO_PIN_12; // CS (GPIO) = L } void spi_eep_cs_high() { GPIO_BOP(GPIOB) = GPIO_PIN_12; // CS (GPIO) = H } /* SPI 指定 byte 数データ書き込み */ void longan_spi_write_byte(uint8_t *data, uint8_t length) { int i; spi_eep_cs_low(); spi_eep_wp_high(); spi_eep_hold_high(); delay_1ms(1); for( i = 0; i < length; i++ ) { while(RESET == spi_i2s_flag_get(SPI1, SPI_FLAG_TBE)); spi_i2s_data_transmit(SPI1, data[i]); } delay_1ms(1); spi_eep_cs_high(); spi_eep_wp_low(); spi_eep_hold_low(); delay_1ms(1); } /* SPI 1byte データ読み出し */ void longan_spi_read_byte(uint8_t *wdata, uint8_t *rdata, uint8_t length) { int i; uint8_t str[20] = {0}; spi_eep_cs_low(); spi_eep_wp_high(); spi_eep_hold_high(); delay_1ms(1); for( i = 0; i < length; i++ ) { while(RESET == spi_i2s_flag_get(SPI1, SPI_FLAG_TBE)); spi_i2s_data_transmit(SPI1, wdata[i]); while(RESET == spi_i2s_flag_get(SPI1, SPI_FLAG_RBNE)); rdata[i] = spi_i2s_data_receive(SPI1); } while(RESET == spi_i2s_flag_get(SPI1, SPI_FLAG_RBNE)); rdata[i] = spi_i2s_data_receive(SPI1); delay_1ms(1); spi_eep_cs_high(); spi_eep_wp_low(); spi_eep_hold_low(); delay_1ms(1); } /* EEPROM データ書き込み */ void longan_spi_eeprom_write(uint16_t addr, uint8_t data) { uint8_t buf[20] = {0}; uint8_t addr_h = (uint8_t)((addr & 0xFF00) >> 8); uint8_t addr_l = (uint8_t)(addr & 0x00FF); buf[0] = 0x06; longan_spi_write_byte(buf, 1); buf[0] = 0x02; buf[1] = addr_h; buf[2] = addr_l; buf[3] = data; longan_spi_write_byte(buf, 4); buf[0] = 0x04; longan_spi_write_byte(buf, 1); snprintf(buf, 20, "A : %x%x D : %x", addr_h, addr_l, data); LCD_ShowString( 5, 5, buf, GREEN ); } /* EEPROM データ読み出し */ uint8_t longan_spi_eeprom_read(uint16_t addr) { uint8_t buf[20] = {0}; uint8_t rbuf[20] = {0}; uint8_t str[20] = {0}; uint8_t addr_h = (uint8_t)((addr & 0xFF00) >> 8); uint8_t addr_l = (uint8_t)(addr & 0x00FF); buf[0] = 0x03; buf[1] = addr_h; buf[2] = addr_l; buf[3] = 0x00; longan_spi_read_byte(buf, rbuf, 4); snprintf(str, 20, "D : %x %x %x %x %x", rbuf[0], rbuf[1], rbuf[2], rbuf[3], rbuf[4]); LCD_ShowString( 5, 30, str, GREEN ); //snprintf(str, 20, "D : %x %x %x %x", rbuf[4], rbuf[5], rbuf[6], rbuf[7]); //LCD_ShowString( 5, 55, str, GREEN ); return rbuf[4]; }
int main(void) { u8 data[2]; u8 buf[12]; longan_led_init(); Lcd_Init(); // LCD を初期化 LCD_Clear( CYAN ); // LCD をクリア BACK_COLOR = BLACK; // 文字の背景色 longan_spi_eeprom_init(); spi_eep_wp_low(); spi_eep_hold_low(); spi_eep_cs_high(); delay_1ms(100); longan_spi_eeprom_write(0x0012, 0xAA); /* アドレス 0x0012 にデータ 0xAA を書き込み*/ data[0] = longan_spi_eeprom_read(0x0012); /* アドレス 0x0012 を読み出し */ snprintf(buf, 20, "D = %x", data[0]); LCD_ShowString( 5, 55, buf, GREEN ); while(1) { i2c_read(0x48, data, 2); snprintf(buf, 12, "Temp = %d.", data[0]); LCD_ShowString( 5, 10, buf, GREEN ); /* turn on builtin led */ longan_led_on(); delay_1ms(100); /* turn off uiltin led */ longan_led_off(); delay_1ms(100); } }
実行結果
書き込み時、読み出し時それぞれの波形を示します.
参考
プログラムの作成にあたっては、以下を参考とさせていただきました.Programmer All