|
作為I2C從機(jī)程序,關(guān)鍵變量aReceiveBuffer以及關(guān)鍵常量I2C0_SLAVE_ADDRESS7,第一個(gè)是I2C設(shè)備寄存器內(nèi)容,第二個(gè)是I2C地址. 當(dāng)上位機(jī)讀寫寄存器時(shí)候,實(shí)際上讀寫的是aReceiveBuffer的內(nèi)容,除了0x00這個(gè)之外,其他全部可以讀寫.算是比較方便實(shí)現(xiàn)某些功能. 編譯器:toolchain-gd32v 9.2.0 [GCC] #include "gd32vf103.h"
#include "systick.h"
#include <stdio.h>
#include <stdint.h>
/* 這里指定的地址是0x41. */
#define I2C0_SLAVE_ADDRESS7 0x82
uint8_t ubRegIndex = 0;
uint8_t aReceiveBuffer[255];
/* GD32VF103 I2C 事件處理模塊 */
void I2C0_EV_IRQHandler(void)
{
/* 收到地址請求 */
if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_ADDSEND))
{
i2c_interrupt_flag_clear(I2C0, I2C_INT_FLAG_ADDSEND);
/* 收到主機(jī)寫入有2個(gè)可能,寫地址/寫數(shù)據(jù). */
}
else if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_RBNE))
{
if (ubRegIndex == 0)
{
ubRegIndex = i2c_data_receive(I2C0);
}
else
{
aReceiveBuffer[ubRegIndex++] = i2c_data_receive(I2C0);
}
/* 收到主機(jī)讀取就應(yīng)該把讀取內(nèi)容送上 */
}
else if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_TBE))
{
i2c_data_transmit(I2C0, aReceiveBuffer[ubRegIndex++]);
/* 如果收到主機(jī)停,那應(yīng)該停. */
}
else if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_STPDET))
{
i2c_stop_on_bus(I2C0);
ubRegIndex = 0;
/* 如果收到的是NACK,也代表主機(jī)不想再發(fā)數(shù)據(jù)了. */
}
else if (i2c_interrupt_flag_get(I2C0, I2C_INT_FLAG_AERR))
{
ubRegIndex = 0;
}
}
void I2C0_ER_IRQHandler(void)
{
}
int main(void)
{
/* 時(shí)鐘初始化 */
rcu_periph_clock_enable(RCU_GPIOB);
rcu_periph_clock_enable(RCU_I2C0);
/* I2C GPIO 初始化 : PB6 => I2C0_SCL,PB7 => I2C0_SDA */
gpio_init(GPIOB, GPIO_MODE_AF_OD, GPIO_OSPEED_50MHZ, GPIO_PIN_6 | GPIO_PIN_7);
/* 復(fù)位I2C外設(shè) */
i2c_software_reset_config(I2C0, I2C_SRESET_SET);
i2c_software_reset_config(I2C0, I2C_SRESET_RESET);
/* I2C時(shí)鐘配置,作為從機(jī),這個(gè)不重要. */
i2c_clock_config(I2C0, 100000, I2C_DTCY_2);
/* I2C地址配置 */
i2c_mode_addr_config(I2C0, I2C_I2CMODE_ENABLE, I2C_ADDFORMAT_7BITS, I2C0_SLAVE_ADDRESS7);
/* 使能I2C */
i2c_enable(I2C0);
/* 允許ACK */
i2c_ack_config(I2C0, I2C_ACK_ENABLE);
/* 開啟中斷事務(wù)處理 */
i2c_interrupt_enable(I2C0, I2C_INT_ERR);
i2c_interrupt_enable(I2C0, I2C_INT_EV);
i2c_interrupt_enable(I2C0, I2C_INT_BUF);
eclic_global_interrupt_enable();
eclic_irq_enable(I2C0_EV_IRQn, 1, 0);
while (1)
{
}
}
效果演示.
為了可讀性,就沒必要脫褲子放屁寫寄存器版本了,我相信編譯器能把這點(diǎn)差距抹平,就這么用吧. |
|
|