123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124 |
- #include "main.h"
- /**
- * @brief Check I2C for errors.
- * @retval I2C return code
- */
- int8_t i2c_check_err(void) {
- int8_t r = I2C_RET_OK;
- if ((I2C1->ISR & I2C_ISR_NACKF) != 0) {
- /* device not present */
- r = I2C_RET_NACK;
- } else if ((I2C1->ISR & (I2C_ISR_ARLO | I2C_ISR_BERR)) != 0) {
- /* other error */
- r = I2C_RET_ERR;
- }
- if (r != I2C_RET_OK) {
- /* restart I2C and clear flags */
- I2C1->CR1 &= ~I2C_CR1_PE;
- while ((I2C1->CR1 & I2C_CR1_PE) != 0);
- I2C1->CR1 |= I2C_CR1_PE;
- }
- return r;
- }
- /**
- * @brief Read len bytes from I2C bus to data by reg_addr.
- * @retval I2C return code
- */
- int8_t user_i2c_read(const uint8_t id, const uint8_t reg_addr, uint8_t *data, const uint16_t len) {
- int8_t r = I2C_RET_OK;
- Flag.I2C_RX_End = 0;
- Flag.I2C_RX_Err = 0;
- Flag.I2C_TX_Err = 0;
- /* wait for i2c */
- while ( I2C1->ISR & I2C_ISR_BUSY ) { __NOP(); };
- /* prepare i2c for sending reg addr */
- I2C1->CR2 &= ~( I2C_CR2_SADD | I2C_CR2_NBYTES | I2C_CR2_RD_WRN);
- I2C1->CR2 |= ( id | 1 << I2C_CR2_NBYTES_Pos );
- /* gen START */
- I2C1->CR2 |= ( I2C_CR2_START );
- /* wait for byte request or any error */
- while ((I2C1->ISR & (I2C_ISR_ARLO | I2C_ISR_BERR | I2C_ISR_NACKF | I2C_ISR_TXE)) == 0) { __NOP(); };
- if ((I2C1->ISR & I2C_ISR_TXE) != 0) {
- /* device ok, send reg addr */
- I2C1->TXDR = reg_addr;
- } else {
- r = i2c_check_err();
- if (r != I2C_RET_OK) {
- Flag.I2C_TX_Err = 1;
- return r;
- }
- }
- /* wait for i2c or any error */
- while (((I2C1->ISR & I2C_ISR_BUSY) != 0) && ((I2C1->ISR & (I2C_ISR_ARLO | I2C_ISR_BERR | I2C_ISR_NACKF)) == 0)) { __NOP(); };
- r = i2c_check_err();
- if (r != I2C_RET_OK) {
- Flag.I2C_TX_Err = 1;
- return r;
- }
- /* prepare dma channel for receiving data */
- DMA1_Channel2->CMAR = (uint32_t)data;
- DMA1_Channel2->CPAR = (uint32_t)&(I2C1->RXDR);
- DMA1_Channel2->CNDTR = len;
- DMA1_Channel2->CCR |= DMA_CCR_EN;
- /* prepare i2c for receiving data */
- I2C1->CR2 &= ~( I2C_CR2_SADD | I2C_CR2_NBYTES | I2C_CR2_RD_WRN);
- I2C1->CR2 |= ( id | len << I2C_CR2_NBYTES_Pos | I2C_CR2_RD_WRN);
- /* launch receiving */
- I2C1->CR1 |= ( I2C_CR1_RXDMAEN );
- I2C1->CR2 |= ( I2C_CR2_START );
- /* wait for receiving data */
- while ((Flag.I2C_RX_End == 0) && (Flag.I2C_RX_Err == 0)) { __NOP(); };
- return r;
- }
- /**
- * @brief Write len bytes to I2C bus from data by reg_addr.
- * @retval I2C return code
- */
- int8_t user_i2c_write(const uint8_t id, const uint8_t reg_addr, uint8_t *data, const uint16_t len) {
- int8_t r = I2C_RET_OK;
- Flag.I2C_TX_End = 0;
- Flag.I2C_TX_Err = 0;
- DMA1_Channel3->CMAR = (uint32_t)data;
- DMA1_Channel3->CPAR = (uint32_t)&(I2C1->TXDR);
- DMA1_Channel3->CNDTR = len;
- while ( I2C1->ISR & I2C_ISR_BUSY );
- I2C1->CR2 &= ~( I2C_CR2_SADD | I2C_CR2_NBYTES | I2C_CR2_RD_WRN);
- I2C1->CR2 |= ( id | (len + 1) << I2C_CR2_NBYTES_Pos );
- I2C1->CR2 |= ( I2C_CR2_START );
- while ((I2C1->ISR & (I2C_ISR_ARLO | I2C_ISR_BERR | I2C_ISR_NACKF | I2C_ISR_TXE)) == 0) { __NOP(); };
- if ((I2C1->ISR & I2C_ISR_TXE) != 0) {
- I2C1->TXDR = reg_addr;
- } else {
- r = i2c_check_err();
- if (r != I2C_RET_OK) {
- Flag.I2C_TX_Err = 1;
- return r;
- }
- }
- DMA1_Channel3->CCR |= DMA_CCR_EN;
- I2C1->CR1 |= ( I2C_CR1_TXDMAEN );
- return r;
- }
|