芯科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;
}
}
完

浙公网安备 33010602011771号