![](/img/trans.png)
[英]STM32 I2C Slave Receiving Executed Only Once with DMA in HAL Library
[英]STM32 I2C Only Transmits Once
我使用 stm32f3 數據表作為寄存器級編程而不是 HAL 的參考。 我很確定我正確設置了所有內容,因為我實際上能夠通過 I2C 外設傳輸數據字節,但是當我將從地址更改為不同的設備(從加速度計到磁力計)時它無法發送一個字節我得到一個 NACK和停止條件。 為什么會這樣?
這是我的時鍾設置:
void ResetClockControl() {
RCC->CFGR |= RCC_CFGR_SW_PLL|RCC_CFGR_HPRE_DIV1|RCC_CFGR_PPRE1_DIV2|RCC_CFGR_PPRE2_DIV1
|RCC_CFGR_PLLSRC_HSE_PREDIV|RCC_CFGR_PLLXTPRE_HSE_PREDIV_DIV1|RCC_CFGR_PLLMUL6|RCC_CFGR_MCO_NOCLOCK;
RCC->CR &= ~(RCC_CR_HSION); //Turn off HSI
RCC->CSR &= ~(RCC_CSR_LSION); //Turn off LSI
/* Set bit PLLON last and wait until it is locked */
RCC->CR |= RCC_CR_HSEON|RCC_CR_HSEBYP|RCC_CR_PLLON;
while(!(RCC->CR & RCC_CR_PLLRDY));}
這是我的 I2C 初始化函數(也初始化從寄存器設置):
void I2C_Init() {
/* Peripheral Clock Enable */
RCC->APB1ENR |= RCC_APB1ENR_I2C1EN; //Enable clock to I2C
RCC->AHBENR |= RCC_AHBENR_GPIOBEN|RCC_AHBENR_DMA1EN; // GPIO/DMA Init
RCC->CFGR3 |= RCC_CFGR3_I2C1SW_SYSCLK; //Set SYSCLK as source
/* GPIO Configuration */
GPIOB->MODER |= GPIO_MODER_MODER6_1|GPIO_MODER_MODER7_1;//alternate function
GPIOB->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR6|GPIO_OSPEEDER_OSPEEDR7;
GPIOB->OTYPER |= GPIO_OTYPER_OT_6|GPIO_OTYPER_OT_7; //open drain
GPIOB->PUPDR |= GPIO_PUPDR_PUPDR6_0|GPIO_PUPDR_PUPDR7_0; // pulllup
GPIOB->AFR[0] |= 0x04000000|0x40000000; ; //AF for SCL and SDA no bit values in
header...
/* Configure DMA Rx */
DMA1_Channel7->CNDTR |= 0x0006; //6 bytes of acc/mag data to be transferred
DMA1_Channel7->CPAR = (uint32_t)&I2C1->RXDR;//0x40005424 I2C receive register address
DMA1_Channel7->CMAR = (uint32_t)test; // DMA memory address to write to
DMA1_Channel7->CCR |= DMA_CCR_EN|DMA_CCR_CIRC|DMA_CCR_MINC|DMA_CCR_TCIE; //memory
increase, interrupt is not enabled assumed to be completed. Circular mode
/* I2c Configuration */
I2C1->TIMINGR |= 0x2010091A; //400KHz fast mode generated from cubeMX
I2C1->CR1 |= I2C_CR1_PE|I2C_CR1_RXDMAEN;// DMA Rx Enable
/* LSM303AGR_Init(); */
uint8_t Data[2] = {0};
Data[0]= 0x20;
Data[1]= 0x57;
I2C_WriteByte(0x19<<1,Data);
Data[0]= 0x23;
Data[1]= 0x20;
I2C_WriteByte(0x19<<1,Data);
Data[0]= 0x60;
Data[1]= 0x0C;
I2C_WriteByte(0x1E<<1,Data);
Data[0]= 0x62;
Data[1]= 0x10;
I2C_WriteByte(0x1E<<1,Data);
}
void I2C_WriteByte(uint8_t sAddress,uint8_t* sData) {
I2C1->CR2 |= 0x02<<I2C_CR2_NBYTES_Pos|sAddress; //NbyteToWrite,slave address,Read/Write
I2C1->CR2 |= I2C_CR2_START; //Start I2C transfer
while(!(I2C1->ISR & I2C_ISR_TXIS)){} //wait until ready to send byte
I2C1->TXDR = sData[0]; //sub reg
while(!(I2C1->ISR & I2C_ISR_TXIS)){} //wait until ready to send byte
I2C1->TXDR = sData[1]; //data
I2C1->CR2 |= I2C_CR2_STOP;
I2C1->ICR |= I2C_ICR_STOPCF;
}
這兩個函數是從 main 調用的。 首先調用 ResetClockControl。
此外,時序寄存器值是由 CubeMX 生成的(肯定我在這里設置的 cubeMX 與時鍾參數相同)
任何人都可以在這里找出問題嗎?
謝謝
不知道為什么會這樣,但在我切換到 I2C 總線上的另一個從設備之前,我需要將我打算發送的字節數重置為 0。我在 2 個從設備傳輸之間使用這條線來執行此操作:
I2C1->CR2 = 0x00<<I2C_CR2_NBYTES_Pos; //切換從機地址時重置NBYTES
我在數據表中找不到任何地方說我必須在切換從設備之前重置 NBYTES 或任何其他原因重置 NBYTES,但這似乎對我有用。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.