FW版本是1.12;
使用IC是STM32L0F4U;
CUBEMX配置,使用LL库。
前提:因为从机的IIC是非标准协议,第一个字节不是控制R/W, 不能用HAL库解决,想使用LL库或者寄存器方式来实现,从设备没有问题,使用模拟方式能够实现。
问题:I2C_TXDR这个寄存器的数据,发送不出去。
完全采用LL库函数,其初始化函数如下,频率是400K 、
- /* I2C1 init function */
- void MX_I2C1_Init(void)
- {
- /* USER CODE BEGIN I2C1_Init 0 */
- // LL_RCC_ClocksTypeDef rcc_clocks;
- /* USER CODE END I2C1_Init 0 */
- LL_I2C_InitTypeDef I2C_InitStruct = {0};
- LL_GPIO_InitTypeDef GPIO_InitStruct = {0};
- LL_IOP_GRP1_EnableClock(LL_IOP_GRP1_PERIPH_GPIOA);
- /**I2C1 GPIO Configuration
- PA9 ------> I2C1_SCL
- PA10 ------> I2C1_SDA
- */
- GPIO_InitStruct.Pin = LL_GPIO_PIN_9;
- GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
- GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH;
- GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_OPENDRAIN;
- GPIO_InitStruct.Pull = LL_GPIO_PULL_UP;
- GPIO_InitStruct.Alternate = LL_GPIO_AF_1;
- LL_GPIO_Init(GPIOA, &GPIO_InitStruct);
- GPIO_InitStruct.Pin = LL_GPIO_PIN_10;
- GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
- GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH;
- GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_OPENDRAIN;
- GPIO_InitStruct.Pull = LL_GPIO_PULL_UP;
- GPIO_InitStruct.Alternate = LL_GPIO_AF_1;
- LL_GPIO_Init(GPIOA, &GPIO_InitStruct);
- /* Peripheral clock enable */
- LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_I2C1);
- /* USER CODE BEGIN I2C1_Init 1 */
- //
- //// LL_I2C_Disable(I2C1);
- /* USER CODE END I2C1_Init 1 */
- /** I2C Initialization
- */
- LL_I2C_EnableAutoEndMode(I2C1);
- LL_I2C_DisableOwnAddress2(I2C1);
- LL_I2C_DisableGeneralCall(I2C1);
- LL_I2C_EnableClockStretching(I2C1);
- I2C_InitStruct.PeripheralMode = LL_I2C_MODE_I2C;
- I2C_InitStruct.Timing = 0x00601B28;
- I2C_InitStruct.AnalogFilter = LL_I2C_ANALOGFILTER_ENABLE;
- I2C_InitStruct.DigitalFilter = 0;
- I2C_InitStruct.OwnAddress1 = 0;
- I2C_InitStruct.TypeAcknowledge = LL_I2C_ACK;
- I2C_InitStruct.OwnAddrSize = LL_I2C_OWNADDRESS1_7BIT;
- LL_I2C_Init(I2C1, &I2C_InitStruct);
- LL_I2C_SetOwnAddress2(I2C1, 0, LL_I2C_OWNADDRESS2_NOMASK);
- /* USER CODE BEGIN I2C1_Init 2 */
- LL_I2C_Enable(I2C1);
- I2C_write();
- /* 5.使能I2C外设. */
- /* USER CODE END I2C1_Init 2 */
- }
复制代码 其中I2C_write()的函数内容是
- while(LL_I2C_IsActiveFlag_BUSY(I2Cx) == SET){
- counter++;
- if( counter == 25000 ) {//
- Error_Handler();
- return ERROR;
- }
- }
- LL_I2C_TransmitData8(I2Cx, addr_reg);
- // I2Cx->CR2 |= I2C_CR2_START; /* 启动 */
- while(LL_I2C_IsActiveFlag_TXE(I2Cx)==RESET)
- {
- LL_mDelay(1);
- LL_I2C_TransmitData8(I2Cx, addr_reg);
- // I2Cx->CR2 |= I2C_CR2_START; /* 启动 */
- }
复制代码 LL_I2C_TransmitData8() 这个库函数完全发送不出来数据,示波器抓取不到波形,TXE位一直是reset。如果使用这一条I2Cx->CR2 |= I2C_CR2_START; /* 启动 */,这能发出波形,但是数据类容并非LL_I2C_TransmitData8中的数据,而是配置的从机地址。
如果调用LL_I2C_HandleTransfer() 这个函数,则能发出来波形,但是这个函数会自动调整R/W位,所以不能在第一个字节使用。
使用这个方法未能实现我需要的功能。
方法二:利用手册中的示例代码,完全寄存器操作,配置好IIC和GPIIO,配置如下:
- RCC->IOPENR |= RCC_IOPENR_GPIOBEN;
-
- /* (1) PU for I2C signals */
- /* (2) open drain for I2C signals */
- /* (3) AF5 for I2C signals */
- /* (4) Select AF mode (10) on PB13 and PB14 */
- GPIOA->PUPDR = (GPIOA->PUPDR & ~(GPIO_PUPDR_PUPD9 | GPIO_PUPDR_PUPD10)) \
- | (GPIO_PUPDR_PUPD9_0 | GPIO_PUPDR_PUPD10_0); /* (1) */
- GPIOA->OTYPER |= GPIO_OTYPER_OT_9 | GPIO_OTYPER_OT_10; /* (2) */
- GPIOA->AFR[1] = (GPIOA->AFR[1] & ~((0xF << ( 1 * 4 )) | (0xF << ( 2 * 4 )))) \
- | (1 << ( 1 * 4 )) | (1 << ( 2 * 4 )); /* (3) */
- GPIOA->MODER = (GPIOA->MODER & ~(GPIO_MODER_MODE9 | GPIO_MODER_MODE10)) \
- | (GPIO_MODER_MODE9_1 | GPIO_MODER_MODE10_1); /* (4) */
- /* Enable the peripheral clock I2C2 */
- RCC->APB1ENR |= RCC_APB1ENR_I2C1EN;
- /* Configure I2C2, master */
- /* (1) Timing register value is computed with the AN4235 xls file,
- fast Mode @400kHz with I2CCLK = 16MHz, rise time = 100ns,
- fall time = 10ns */
- /* (2) Periph enable, receive interrupt enable */
- /* (3) Slave address = 0x5A, read transfer, 1 byte to receive, autoend */
- I2C1->TIMINGR = (uint32_t)0x00300619; /* (1) */
- I2C1->CR1 = I2C_CR1_PE; /* (2) */
- I2C1->CR2 = I2C_CR2_AUTOEND | (1<<16) | (0X5A<<1); /* (3) */
复制代码 调用如下:
- while(1){
- if((I2Cx->ISR & I2C_ISR_TXE) == (I2C_ISR_TXE)) /* Check Tx empty */
- {
- I2Cx->TXDR = 0x48; /* Byte to send */
- I2Cx->CR2 |= I2C_CR2_START; /* Go */
- }
- LL_mDelay(1);
- }
复制代码 发的数据也不是0x48,而是从机地址0x5A<<1 .
实在没招了,求大佬指点
|
本来之前就是模拟方式做的, 发现耗时还是有500us,想优化一下,使用硬件方式试试,现在出不来想要的结果