b49c9ab0c6
完整实现了以下模块: - 系统数据总线(sys_data_bus)模块间通信 - UART/USART/LPUART驱动 + RS485半双工 - I2C驱动(AS5600角度传感器 + AT24C02 EEPROM) - Modbus RTU从站协议 - 步进电机微步进控制(正弦/余弦换相+S曲线加减速) - 到位开关驱动(DI_MIN/DI_MAX) - PGA+ADC电流检测 - 系统监控任务(内存/串口/传感器/任务状态) - LED/Key外设驱动 - 基于CMake + arm-none-eabi-gcc构建系统
156 lines
3.3 KiB
C
156 lines
3.3 KiB
C
#include "i2c_driver.h"
|
|
#include "py32md530.h"
|
|
#include "system_py32md530.h"
|
|
#include "config.h"
|
|
|
|
#define I2C_TIMEOUT 10000
|
|
|
|
static void i2c_wait_flag(uint32_t flag)
|
|
{
|
|
uint32_t timeout = I2C_TIMEOUT;
|
|
while (!(I2C1->ISR & flag)) {
|
|
if (--timeout == 0) break;
|
|
}
|
|
}
|
|
|
|
ret_code_t i2c_init(uint32_t speed)
|
|
{
|
|
uint32_t timing;
|
|
|
|
RCC->APB1ENR |= RCC_APB1ENR_I2C1EN;
|
|
|
|
I2C1->CR1 &= ~I2C_CR1_PE_Msk;
|
|
|
|
timing = (SystemCoreClock / speed) - 1;
|
|
if (timing > 0x3F) timing = 0x3F;
|
|
I2C1->TIMINGR = timing;
|
|
|
|
I2C1->CR1 = I2C_CR1_PE_Msk;
|
|
|
|
return RET_OK;
|
|
}
|
|
|
|
ret_code_t i2c_deinit(void)
|
|
{
|
|
I2C1->CR1 &= ~I2C_CR1_PE_Msk;
|
|
RCC->APB1ENR &= ~RCC_APB1ENR_I2C1EN;
|
|
return RET_OK;
|
|
}
|
|
|
|
ret_code_t i2c_master_write(uint8_t dev_addr, const uint8_t *data, uint32_t len)
|
|
{
|
|
uint32_t i;
|
|
|
|
I2C1->CR2 = (dev_addr << 1)
|
|
| (len << 16)
|
|
| (1UL << 13);
|
|
|
|
I2C1->CR2 |= (1UL << 14);
|
|
|
|
i2c_wait_flag(I2C_ISR_TXIS_Msk);
|
|
|
|
for (i = 0; i < len; i++) {
|
|
I2C1->TXDR = data[i];
|
|
if (i < len - 1) {
|
|
i2c_wait_flag(I2C_ISR_TXIS_Msk);
|
|
}
|
|
}
|
|
|
|
i2c_wait_flag(I2C_ISR_STOPF_Msk);
|
|
I2C1->ICR |= I2C_ISR_STOPF_Msk;
|
|
|
|
return RET_OK;
|
|
}
|
|
|
|
ret_code_t i2c_master_read(uint8_t dev_addr, uint8_t *data, uint32_t len)
|
|
{
|
|
uint32_t i;
|
|
|
|
I2C1->CR2 = (dev_addr << 1)
|
|
| (len << 16)
|
|
| (1UL << 13);
|
|
|
|
I2C1->CR2 |= (1UL << 14);
|
|
|
|
for (i = 0; i < len; i++) {
|
|
i2c_wait_flag(I2C_ISR_RXNE_Msk);
|
|
data[i] = (uint8_t)I2C1->RXDR;
|
|
}
|
|
|
|
i2c_wait_flag(I2C_ISR_STOPF_Msk);
|
|
I2C1->ICR |= I2C_ISR_STOPF_Msk;
|
|
|
|
return RET_OK;
|
|
}
|
|
|
|
ret_code_t i2c_mem_write(uint8_t dev_addr, uint16_t mem_addr, uint8_t mem_addr_size, const uint8_t *data, uint32_t len)
|
|
{
|
|
uint8_t buf[len + 2];
|
|
uint32_t i;
|
|
|
|
if (mem_addr_size == 1) {
|
|
buf[0] = (uint8_t)(mem_addr & 0xFF);
|
|
} else {
|
|
buf[0] = (uint8_t)((mem_addr >> 8) & 0xFF);
|
|
buf[1] = (uint8_t)(mem_addr & 0xFF);
|
|
}
|
|
|
|
for (i = 0; i < len; i++) {
|
|
buf[mem_addr_size + i] = data[i];
|
|
}
|
|
|
|
return i2c_master_write(dev_addr, buf, len + mem_addr_size);
|
|
}
|
|
|
|
ret_code_t i2c_mem_read(uint8_t dev_addr, uint16_t mem_addr, uint8_t mem_addr_size, uint8_t *data, uint32_t len)
|
|
{
|
|
uint8_t addr_buf[2];
|
|
|
|
if (mem_addr_size == 1) {
|
|
addr_buf[0] = (uint8_t)(mem_addr & 0xFF);
|
|
} else {
|
|
addr_buf[0] = (uint8_t)((mem_addr >> 8) & 0xFF);
|
|
addr_buf[1] = (uint8_t)(mem_addr & 0xFF);
|
|
}
|
|
|
|
I2C1->CR2 = (dev_addr << 1)
|
|
| (mem_addr_size << 16)
|
|
| (1UL << 13);
|
|
|
|
I2C1->CR2 |= (1UL << 14);
|
|
|
|
if (mem_addr_size == 1) {
|
|
i2c_wait_flag(I2C_ISR_TXIS_Msk);
|
|
I2C1->TXDR = addr_buf[0];
|
|
} else {
|
|
i2c_wait_flag(I2C_ISR_TXIS_Msk);
|
|
I2C1->TXDR = addr_buf[0];
|
|
i2c_wait_flag(I2C_ISR_TXIS_Msk);
|
|
I2C1->TXDR = addr_buf[1];
|
|
}
|
|
|
|
i2c_wait_flag(I2C_ISR_STOPF_Msk);
|
|
I2C1->ICR |= I2C_ISR_STOPF_Msk;
|
|
|
|
return i2c_master_read(dev_addr, data, len);
|
|
}
|
|
|
|
ret_code_t i2c_check_device(uint8_t dev_addr)
|
|
{
|
|
I2C1->CR2 = (dev_addr << 1)
|
|
| (0 << 16)
|
|
| (1UL << 13);
|
|
|
|
I2C1->CR2 |= (1UL << 14);
|
|
|
|
i2c_wait_flag(I2C_ISR_STOPF_Msk);
|
|
I2C1->ICR |= I2C_ISR_STOPF_Msk;
|
|
|
|
if (I2C1->ISR & I2C_ISR_NACKF_Msk) {
|
|
I2C1->ICR |= I2C_ISR_NACKF_Msk;
|
|
return RET_ERROR;
|
|
}
|
|
|
|
return RET_OK;
|
|
}
|