你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

STM32L0 LL库 IIC 配置和使用的问题,发送不出我想要的数据。求指点

[复制链接]
麻袋 提问时间:2021-7-2 15:59 / 未解决
FW版本是1.12;
使用IC是STM32L0F4U;
CUBEMX配置,使用LL库。
前提:因为从机的IIC是非标准协议,第一个字节不是控制R/W, 不能用HAL库解决,想使用LL库或者寄存器方式来实现,从设备没有问题,使用模拟方式能够实现。
问题:I2C_TXDR这个寄存器的数据,发送不出去。
完全采用LL库函数,其初始化函数如下,频率是400K 、
  1. /* I2C1 init function */
  2. void MX_I2C1_Init(void)
  3. {

  4.   /* USER CODE BEGIN I2C1_Init 0 */
  5. //        LL_RCC_ClocksTypeDef rcc_clocks;
  6.   /* USER CODE END I2C1_Init 0 */

  7.   LL_I2C_InitTypeDef I2C_InitStruct = {0};

  8.   LL_GPIO_InitTypeDef GPIO_InitStruct = {0};

  9.   LL_IOP_GRP1_EnableClock(LL_IOP_GRP1_PERIPH_GPIOA);
  10.   /**I2C1 GPIO Configuration
  11.   PA9   ------> I2C1_SCL
  12.   PA10   ------> I2C1_SDA
  13.   */
  14.   GPIO_InitStruct.Pin = LL_GPIO_PIN_9;
  15.   GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
  16.   GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH;
  17.   GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_OPENDRAIN;
  18.   GPIO_InitStruct.Pull = LL_GPIO_PULL_UP;
  19.   GPIO_InitStruct.Alternate = LL_GPIO_AF_1;
  20.   LL_GPIO_Init(GPIOA, &GPIO_InitStruct);

  21.   GPIO_InitStruct.Pin = LL_GPIO_PIN_10;
  22.   GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
  23.   GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH;
  24.   GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_OPENDRAIN;
  25.   GPIO_InitStruct.Pull = LL_GPIO_PULL_UP;
  26.   GPIO_InitStruct.Alternate = LL_GPIO_AF_1;
  27.   LL_GPIO_Init(GPIOA, &GPIO_InitStruct);

  28.   /* Peripheral clock enable */
  29.   LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_I2C1);

  30.   /* USER CODE BEGIN I2C1_Init 1 */
  31. //       
  32. ////        LL_I2C_Disable(I2C1);
  33.   /* USER CODE END I2C1_Init 1 */
  34.   /** I2C Initialization
  35.   */
  36.   LL_I2C_EnableAutoEndMode(I2C1);
  37.   LL_I2C_DisableOwnAddress2(I2C1);
  38.   LL_I2C_DisableGeneralCall(I2C1);
  39.   LL_I2C_EnableClockStretching(I2C1);
  40.   I2C_InitStruct.PeripheralMode = LL_I2C_MODE_I2C;
  41.   I2C_InitStruct.Timing = 0x00601B28;
  42.   I2C_InitStruct.AnalogFilter = LL_I2C_ANALOGFILTER_ENABLE;
  43.   I2C_InitStruct.DigitalFilter = 0;
  44.   I2C_InitStruct.OwnAddress1 = 0;
  45.   I2C_InitStruct.TypeAcknowledge = LL_I2C_ACK;
  46.   I2C_InitStruct.OwnAddrSize = LL_I2C_OWNADDRESS1_7BIT;
  47.   LL_I2C_Init(I2C1, &I2C_InitStruct);
  48.   LL_I2C_SetOwnAddress2(I2C1, 0, LL_I2C_OWNADDRESS2_NOMASK);
  49.   /* USER CODE BEGIN I2C1_Init 2 */

  50.         LL_I2C_Enable(I2C1);

  51.         I2C_write();   
  52.         /* 5.使能I2C外设. */
  53.   /* USER CODE END I2C1_Init 2 */

  54. }
复制代码
其中I2C_write()的函数内容是
  1. while(LL_I2C_IsActiveFlag_BUSY(I2Cx) == SET){
  2.                 counter++;
  3.                 if( counter == 25000 ) {//
  4.                         Error_Handler();
  5.                         return ERROR;
  6.                 }
  7.         }       
  8.         LL_I2C_TransmitData8(I2Cx, addr_reg);
  9. //        I2Cx->CR2 |= I2C_CR2_START; /* 启动 */
  10.         while(LL_I2C_IsActiveFlag_TXE(I2Cx)==RESET)
  11.         {
  12.                 LL_mDelay(1);
  13.                 LL_I2C_TransmitData8(I2Cx, addr_reg);
  14. //                I2Cx->CR2 |= I2C_CR2_START; /* 启动 */
  15.         }
复制代码
LL_I2C_TransmitData8()    这个库函数完全发送不出来数据,示波器抓取不到波形,TXE位一直是reset。如果使用这一条I2Cx->CR2 |= I2C_CR2_START; /* 启动 */,这能发出波形,但是数据类容并非LL_I2C_TransmitData8中的数据,而是配置的从机地址。
如果调用LL_I2C_HandleTransfer() 这个函数,则能发出来波形,但是这个函数会自动调整R/W位,所以不能在第一个字节使用。
使用这个方法未能实现我需要的功能。
方法二:利用手册中的示例代码,完全寄存器操作,配置好IIC和GPIIO,配置如下:
  1.   RCC->IOPENR |= RCC_IOPENR_GPIOBEN;
  2.        
  3.   /* (1) PU for I2C signals */
  4.   /* (2) open drain for I2C signals */
  5.   /* (3) AF5 for I2C signals */
  6.   /* (4) Select AF mode (10) on PB13 and PB14 */
  7.   GPIOA->PUPDR = (GPIOA->PUPDR & ~(GPIO_PUPDR_PUPD9 | GPIO_PUPDR_PUPD10)) \
  8.                  | (GPIO_PUPDR_PUPD9_0 | GPIO_PUPDR_PUPD10_0); /* (1) */
  9.   GPIOA->OTYPER |= GPIO_OTYPER_OT_9 | GPIO_OTYPER_OT_10; /* (2) */
  10.   GPIOA->AFR[1] = (GPIOA->AFR[1] & ~((0xF << ( 1 * 4 )) | (0xF << ( 2 * 4 )))) \
  11.                   | (1 << ( 1 * 4 )) | (1 << ( 2 * 4 )); /* (3) */
  12.   GPIOA->MODER = (GPIOA->MODER & ~(GPIO_MODER_MODE9 | GPIO_MODER_MODE10)) \
  13.                  | (GPIO_MODER_MODE9_1 | GPIO_MODER_MODE10_1); /* (4) */
  14.     /* Enable the peripheral clock I2C2 */
  15.   RCC->APB1ENR |= RCC_APB1ENR_I2C1EN;

  16.   /* Configure I2C2, master */
  17.   /* (1) Timing register value is computed with the AN4235 xls file,
  18.          fast Mode @400kHz with I2CCLK = 16MHz, rise time = 100ns,
  19.          fall time = 10ns */
  20.   /* (2) Periph enable, receive interrupt enable */
  21.   /* (3) Slave address = 0x5A, read transfer, 1 byte to receive, autoend */
  22.   I2C1->TIMINGR = (uint32_t)0x00300619; /* (1) */
  23.   I2C1->CR1 = I2C_CR1_PE; /* (2) */
  24.   I2C1->CR2 =  I2C_CR2_AUTOEND | (1<<16) | (0X5A<<1); /* (3) */
复制代码
调用如下:
  1. while(1){
  2.                 if((I2Cx->ISR & I2C_ISR_TXE) == (I2C_ISR_TXE)) /* Check Tx empty */
  3.                 {
  4.                   I2Cx->TXDR = 0x48; /* Byte to send */
  5.                   I2Cx->CR2 |= I2C_CR2_START; /* Go */
  6.                 }
  7.                 LL_mDelay(1);
  8.         }
复制代码
发的数据也不是0x48,而是从机地址0x5A<<1 .
实在没招了,求大佬指点
收藏 评论4 发布时间:2021-7-2 15:59

举报

4个回答
老牛洋车 回答时间:2021-7-3 08:37:49
改用模拟I2C如何?
麻袋 回答时间:2021-7-5 13:17:30
老牛洋车 发表于 2021-7-3 08:37
改用模拟I2C如何?

本来之前就是模拟方式做的,  发现耗时还是有500us,想优化一下,使用硬件方式试试,现在出不来想要的结果
butterflyspring 回答时间:2021-7-5 15:07:41
第一个字节不是标准地址和控制读写位,那么可以按照从机的需求把需要的值配给相关的地址寄存器I2C-CR2 ,使得主机发送的地址就是从机需要的值。这个外设是按照标准I2C协议设计的,所以一使能就会发出START+ADDRESS。试试看能不能变通一下。从手册上看,省略不了地址值的发送
STM32L0I2Caddress.PNG
wlp向日葵 回答时间:2021-7-5 20:22:19
你试下用软件模拟IIC,然后用示波器看下波形对不对

所属标签

相似问题

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32Cube扩展软件包
意法半导体边缘AI套件
ST - 理想汽车豪华SUV案例
ST意法半导体智能家居案例
STM32 ARM Cortex 32位微控制器
关注我们
st-img 微信公众号
st-img 手机版