一、工具
1、硬件:GD32F30x系列单片机
2、编译环境:KEIL
3、AD5245芯片:AD5245BRJ10
二、芯片简介
AD5245是一款256位调整可实现与机械电位计或可变电阻相同功能的电子器件。采用2.7V至5.5V电源供电,功耗小于8μA,适合电池供电的便携式应用。游标设置可通过I2C兼容型数字接口控制,也可以利用该接口读回游标寄存器的内容。AD0可以将最多两个器件置于同一总线上。命令位将游标位置复位到中间值或关断器件,使之进入零功耗状态。
A端和B端间RDAC的标称电阻可以为5KΩ、10KΩ、50KΩ和100KΩ。可变电阻的标称电阻(RAB)有256个触点,通过游标端和B端触点访问。RDAC锁存器中的8位数据经过解码,用于选择256种可能的设置之一。
其它具体介绍请看相关手册,这里不再赘述。
三、芯片I2C通讯协议
下图包含了设备地址以及读写时序。
四、硬件电路
五、代码实现
1、设置电位计值函数
/** * @brief 数字电位计值设置 * @param addr 数字电位计设备地址 * @param value 数字电位计设置的值 * @retval none * @author Mr.W * @date 2020-10-25 */ void ad5245_value_set(uint8_t addr, uint8_t value) { uint8_t data[2] = {0}; data[0] = 0; data[1] = (value&0xFF); i2c_write(addr, &data[0], 2); }
2、I2C初始化
/** ***************************************************************************** * @Name : I2C1_GPIO_Configuration * @Brief : I2C1引脚初始化 ***************************************************************************** **/ void I2C1_GPIO_Configuration(void) { rcu_periph_clock_enable(RCU_GPIOB); rcu_periph_clock_enable(RCU_AF); gpio_init(GPIOB, GPIO_MODE_AF_OD, GPIO_OSPEED_50MHZ, GPIO_PIN_10 | GPIO_PIN_11); } /** ***************************************************************************** * @Name : I2C1_Configuration * @Brief : I2C1配置 * @Input : * @Output : * @Return : ***************************************************************************** **/ void I2C1_Configuration(void) { I2C1_GPIO_Configuration(); rcu_periph_clock_enable(RCU_I2C1); i2c_clock_config(I2C1, 250000, I2C_DTCY_2);/*设置I2C频率*/ i2c_mode_addr_config(I2C1, I2C_I2CMODE_ENABLE, I2C_ADDFORMAT_7BITS, 0);/*设置I2C 地址长度*/ i2c_enable(I2C1); i2c_ack_config(I2C1, I2C_ACK_ENABLE);/*开启应答*/ }
3、I2C写
/** * @brief I2C1写函数 * @param addr设备地址 * @param pdata 数据指针 * @param data_length 数据长度 * @retval none * @author Mr.W * @date 2020-11-11 */ void i2c_write(uint8_t addr, uint8_t *pdata, uint32_t data_length) { uint32_t i; /* wait until I2C bus is idle */ while(i2c_flag_get(I2C1, I2C_FLAG_I2CBSY)); /* send a start condition to I2C bus */ i2c_start_on_bus(I2C1); /* wait until SBSEND bit is set */ while(!i2c_flag_get(I2C1, I2C_FLAG_SBSEND)); /* send slave address to I2C bus */ i2c_master_addressing(I2C1, addr, I2C_TRANSMITTER); /* wait until ADDSEND bit is set */ while(!i2c_flag_get(I2C1, I2C_FLAG_ADDSEND)); /* clear ADDSEND bit */ i2c_flag_clear(I2C1, I2C_FLAG_ADDSEND); /* wait until the transmit data buffer is empty */ while(!i2c_flag_get(I2C1, I2C_FLAG_TBE)); for(i = 0; i < data_length; i++){ /* data transmission */ i2c_data_transmit(I2C1, pdata[i]); /* wait until the TBE bit is set */ while(!i2c_flag_get(I2C1, I2C_FLAG_TBE)); } /* send a stop condition to I2C bus */ i2c_stop_on_bus(I2C1); /* wait until stop condition generate */ while(I2C_CTL0(I2C1)&0x0200); }
4、I2C读
/** * @brief I2C1读函数 * @param addr设备地址 * @param pdata 数据指针 * @param data_length 数据长度 * @retval none * @author Mr.W * @date 2020-11-11 */ void i2c_read(uint8_t addr, uint8_t *pdata, uint32_t data_length) { uint32_t i; /* send a NACK for the next data byte which will be received into the shift register */ i2c_ackpos_config(I2C1, I2C_ACKPOS_NEXT); /* wait until I2C bus is idle */ while(i2c_flag_get(I2C1, I2C_FLAG_I2CBSY)); /* send a start condition to I2C bus */ i2c_start_on_bus(I2C1); /* wait until SBSEND bit is set */ while(!i2c_flag_get(I2C1, I2C_FLAG_SBSEND)); /* send slave address to I2C bus */ i2c_master_addressing(I2C1, addr, I2C_RECEIVER); /* disable ACK before clearing ADDSEND bit */ i2c_ack_config(I2C1, I2C_ACK_DISABLE); /* wait until ADDSEND bit is set */ while(!i2c_flag_get(I2C1, I2C_FLAG_ADDSEND)); /* clear ADDSEND bit */ i2c_flag_clear(I2C1, I2C_FLAG_ADDSEND); /* Wait until the last data byte is received into the shift register */ while(!i2c_flag_get(I2C1, I2C_FLAG_BTC)); for(i = 0; i < data_length; i++) { /* wait until the RBNE bit is set */ while(!i2c_flag_get(I2C1, I2C_FLAG_RBNE)); /* read a data from I2C_DATA */ pdata[i] = i2c_data_receive(I2C1); } /* send a stop condition */ i2c_stop_on_bus(I2C1); /* wait until stop condition generate */ while(I2C_CTL0(I2C1)&0x0200); i2c_ackpos_config(I2C1, I2C_ACKPOS_CURRENT); /* enable acknowledge */ i2c_ack_config(I2C1, I2C_ACK_ENABLE); }
#endif