芯科BG22学习笔记:8-如何添加IIC(寄存器配置)
实验目的:BG22芯片添加IIC功能(使用寄存器配置方法)
实验环境:Simplicity Studio V5
实验器材:Wireless Starter Kit Mainboard (BRD4002A Rev B06) + EFR32xG22 2.4 GHz 6 dBm QFN40 Radio Board (BRD4182A)
实验开始:
1. 新建工程,蓝牙工程输入soc empty, 普通MCU工程输入empty c
2. 添加i2c.c和i2c.h两个文件
3. i2c.c添加如下代码
#include <stdio.h> #include "em_device.h" #include "em_chip.h" #include "em_i2c.h" #include "em_cmu.h" #include "em_emu.h" #include "em_gpio.h" #include "i2c.h" // Defines #define I2C_FOLLOWER_ADDRESS 0xE2 #define I2C_TXBUFFER_SIZE 10 #define I2C_RXBUFFER_SIZE 10 // Buffers uint8_t i2c_txBuffer[I2C_TXBUFFER_SIZE]; uint8_t i2c_rxBuffer[I2C_RXBUFFER_SIZE]; // Transmission flags volatile bool i2c_startTx; /***************************************************************************//** * @brief Enable clocks ******************************************************************************/ void initCMU(void) { // Enable clocks to the I2C and GPIO CMU_ClockEnable(cmuClock_I2C0, true); CMU_ClockEnable(cmuClock_GPIO, true); /* * Note: For EFR32xG21 radio devices, library function calls to * CMU_ClockEnable() have no effect as oscillators are automatically turned * on/off based on demand from the peripherals; CMU_ClockEnable() is a dummy * function for EFR32xG21 for library consistency/compatibility. */ } /***************************************************************************//** * @brief GPIO initialization ******************************************************************************/ void initGPIO(void) { // 配置PB0为中断输入 GPIO_PinModeSet(BSP_GPIO_PB0_PORT, BSP_GPIO_PB0_PIN, gpioModeInputPull, 1); GPIO_ExtIntConfig(BSP_GPIO_PB0_PORT, BSP_GPIO_PB0_PIN, 0, false, true, true); // 配置LED0/1为输出 GPIO_PinModeSet(BSP_GPIO_LED0_PORT, BSP_GPIO_LED0_PIN, gpioModePushPull, 0); GPIO_PinModeSet(BSP_GPIO_LED1_PORT, BSP_GPIO_LED1_PIN, gpioModePushPull, 0); // Enable EVEN interrupt to catch button press that starts I2C transfer NVIC_ClearPendingIRQ(GPIO_EVEN_IRQn); NVIC_EnableIRQ(GPIO_EVEN_IRQn); } /***************************************************************************//** * @brief Setup I2C ******************************************************************************/ void initI2C(void) { // Use default settings I2C_Init_TypeDef i2cInit = I2C_INIT_DEFAULT; // Using PA5 (SDA) and PA6 (SCL) GPIO_PinModeSet(gpioPortA, 5, gpioModeWiredAndPullUpFilter, 1); GPIO_PinModeSet(gpioPortA, 6, gpioModeWiredAndPullUpFilter, 1); // Route I2C pins to GPIO GPIO->I2CROUTE[0].SDAROUTE = (GPIO->I2CROUTE[0].SDAROUTE & ~_GPIO_I2C_SDAROUTE_MASK) | (gpioPortA << _GPIO_I2C_SDAROUTE_PORT_SHIFT | (5 << _GPIO_I2C_SDAROUTE_PIN_SHIFT)); GPIO->I2CROUTE[0].SCLROUTE = (GPIO->I2CROUTE[0].SCLROUTE & ~_GPIO_I2C_SCLROUTE_MASK) | (gpioPortA << _GPIO_I2C_SCLROUTE_PORT_SHIFT | (6 << _GPIO_I2C_SCLROUTE_PIN_SHIFT)); GPIO->I2CROUTE[0].ROUTEEN = GPIO_I2C_ROUTEEN_SDAPEN | GPIO_I2C_ROUTEEN_SCLPEN; // Initialize the I2C I2C_Init(I2C0, &i2cInit); // Set the status flags and index i2c_startTx = false; // Enable automatic STOP on NACK I2C0->CTRL = I2C_CTRL_AUTOSN; } /***************************************************************************//** * @brief I2C read numBytes from follower device starting at target address ******************************************************************************/ void I2C_LeaderRead(uint16_t followerAddress, uint8_t targetAddress, uint8_t *rxBuff, uint8_t numBytes) { // Transfer structure I2C_TransferSeq_TypeDef i2cTransfer; I2C_TransferReturn_TypeDef result; // Initialize I2C transfer i2cTransfer.addr = followerAddress; i2cTransfer.flags = I2C_FLAG_WRITE_READ; // must write target address before reading i2cTransfer.buf[0].data = &targetAddress; i2cTransfer.buf[0].len = 1; i2cTransfer.buf[1].data = rxBuff; i2cTransfer.buf[1].len = numBytes; result = I2C_TransferInit(I2C0, &i2cTransfer); // Send data while (result == i2cTransferInProgress) { result = I2C_Transfer(I2C0); } if (result != i2cTransferDone) { // LED1 ON and infinite while loop to indicate I2C transmission problem GPIO_PinOutSet(BSP_GPIO_LED1_PORT, BSP_GPIO_LED1_PIN); while(1); } } /***************************************************************************//** * @brief I2C write numBytes to follower device starting at target address ******************************************************************************/ void I2C_LeaderWrite(uint16_t followerAddress, uint8_t targetAddress, uint8_t *txBuff, uint8_t numBytes) { // Transfer structure I2C_TransferSeq_TypeDef i2cTransfer; I2C_TransferReturn_TypeDef result; uint8_t txBuffer[I2C_TXBUFFER_SIZE + 1]; txBuffer[0] = targetAddress; for(int i = 0; i < numBytes; i++) { txBuffer[i + 1] = txBuff[i]; } // Initialize I2C transfer i2cTransfer.addr = followerAddress; i2cTransfer.flags = I2C_FLAG_WRITE; i2cTransfer.buf[0].data = txBuffer; i2cTransfer.buf[0].len = numBytes + 1; i2cTransfer.buf[1].data = NULL; i2cTransfer.buf[1].len = 0; result = I2C_TransferInit(I2C0, &i2cTransfer); // Send data while (result == i2cTransferInProgress) { result = I2C_Transfer(I2C0); } if (result != i2cTransferDone) { // LED1 ON and infinite while loop to indicate I2C transmission problem GPIO_PinOutSet(BSP_GPIO_LED1_PORT, BSP_GPIO_LED1_PIN); while(1); } } /***************************************************************************//** * @brief I2C Read/Increment/Write/Verify ******************************************************************************/ bool testI2C(void) { int i; bool I2CWriteVerify; // Initial read of bytes from follower I2C_LeaderRead(I2C_FOLLOWER_ADDRESS, 0, i2c_rxBuffer, I2C_RXBUFFER_SIZE); // Increment received values and prepare to write back to follower for (i = 0; i < I2C_RXBUFFER_SIZE; i++) { i2c_txBuffer[i] = i2c_rxBuffer[i] + 1; } // Block write new values to follower I2C_LeaderWrite(I2C_FOLLOWER_ADDRESS, 0, i2c_txBuffer, I2C_TXBUFFER_SIZE); // Block read from follower I2C_LeaderRead(I2C_FOLLOWER_ADDRESS, 0, i2c_rxBuffer, I2C_RXBUFFER_SIZE); // Verify I2C transmission I2CWriteVerify = true; for (i = 0; i < I2C_RXBUFFER_SIZE; i++) { if (i2c_txBuffer[i] != i2c_rxBuffer[i]) { I2CWriteVerify = false; break; } } return I2CWriteVerify; } /***************************************************************************//** * @brief GPIO Interrupt handler ******************************************************************************/ void GPIO_EVEN_IRQHandler(void) { // Clear pending uint32_t interruptMask = GPIO_IntGet(); GPIO_IntClear(interruptMask); // Re-enable I2C I2C_Enable(I2C0, true); i2c_startTx = true; } void I2C_Initial(void) { // Initialize the I2C initCMU(); initGPIO(); initI2C(); } void I2C_Polling(void) { if (i2c_startTx) { // Transmitting data if (testI2C() == false) { // Indicate error with LED1 GPIO_PinOutSet(BSP_GPIO_LED1_PORT, BSP_GPIO_LED1_PIN); // Sit in infinite while loop while(1); } else { // Toggle LED0 with each pass GPIO_PinOutToggle(BSP_GPIO_LED0_PORT, BSP_GPIO_LED0_PIN); // Transmission complete i2c_startTx = false; } } }
4. i2c.h添加如下代码
/* * i2c.h * * Created on: 2024年11月26日 * Author: royw */ #ifndef I2C_H_ #define I2C_H_ extern volatile bool i2c_startTx; #define BSP_GPIO_PB0_PORT gpioPortB #define BSP_GPIO_PB0_PIN 0 #define BSP_GPIO_PB1_PORT gpioPortB #define BSP_GPIO_PB1_PIN 1 #define BSP_GPIO_LED0_PORT gpioPortD #define BSP_GPIO_LED0_PIN 2 #define BSP_GPIO_LED1_PORT gpioPortD #define BSP_GPIO_LED1_PIN 3 void I2C_Initial(void); void I2C_Polling(void); #endif /* I2C_H_ */
5. app.c修改为
#include "em_common.h" #include "app_assert.h" #include "sl_bluetooth.h" #include "app.h" #include "i2c.h" // The advertising set handle allocated from Bluetooth stack. static uint8_t advertising_set_handle = 0xff; /**************************************************************************//** * Application Init. *****************************************************************************/ SL_WEAK void app_init(void) { ///////////////////////////////////////////////////////////////////////////// // Put your additional application init code here! // // This is called once during start-up. // ///////////////////////////////////////////////////////////////////////////// I2C_Initial(); } /**************************************************************************//** * Application Process Action. *****************************************************************************/ SL_WEAK void app_process_action(void) { ///////////////////////////////////////////////////////////////////////////// // Put your additional application code here! // // This is called infinitely. // // Do not call blocking functions from here! // ///////////////////////////////////////////////////////////////////////////// I2C_Polling(); } /**************************************************************************//** * Bluetooth stack event handler. * This overrides the dummy weak implementation. * * @param[in] evt Event coming from the Bluetooth stack. *****************************************************************************/ void sl_bt_on_event(sl_bt_msg_t *evt) { sl_status_t sc; switch (SL_BT_MSG_ID(evt->header)) { // ------------------------------- // This event indicates the device has started and the radio is ready. // Do not call any stack command before receiving this boot event! case sl_bt_evt_system_boot_id: // Create an advertising set. sc = sl_bt_advertiser_create_set(&advertising_set_handle); app_assert_status(sc); // Generate data for advertising sc = sl_bt_legacy_advertiser_generate_data(advertising_set_handle, sl_bt_advertiser_general_discoverable); app_assert_status(sc); // Set advertising interval to 100ms. sc = sl_bt_advertiser_set_timing( advertising_set_handle, 160, // min. adv. interval (milliseconds * 1.6) 160, // max. adv. interval (milliseconds * 1.6) 0, // adv. duration 0); // max. num. adv. events app_assert_status(sc); // Start advertising and enable connections. sc = sl_bt_legacy_advertiser_start(advertising_set_handle, sl_bt_legacy_advertiser_connectable); app_assert_status(sc); break; // ------------------------------- // This event indicates that a new connection was opened. case sl_bt_evt_connection_opened_id: break; // ------------------------------- // This event indicates that a connection was closed. case sl_bt_evt_connection_closed_id: // Generate data for advertising sc = sl_bt_legacy_advertiser_generate_data(advertising_set_handle, sl_bt_advertiser_general_discoverable); app_assert_status(sc); // Restart advertising after client has disconnected. sc = sl_bt_legacy_advertiser_start(advertising_set_handle, sl_bt_legacy_advertiser_connectable); app_assert_status(sc); break; /////////////////////////////////////////////////////////////////////////// // Add additional event handlers here as your application requires! // /////////////////////////////////////////////////////////////////////////// // ------------------------------- // Default event handler. default: break; } }
完