[STM32F4] STM32F407 硬件IIC驱动MCP4017 数字电位器

[复制链接]
2586|10
 楼主| 发给她更好fh 发表于 2023-3-29 12:36 | 显示全部楼层 |阅读模式
前言

MCP4017是一款可以通过IIC接口进行配置的可调电位器,此电位器有128个可配值.因为项目需要我们需要使用MCP4017调节电阻值.来作为其他部分电路的外围电路部分,可在调试的时候灵活配置.
1、STM32F407的硬件IIC使用步骤
1 IIC硬件引脚接口初始化.

首先需要初始化IIC引脚的SCK 和SDA 的模式为GPIO_Mode_AF,然后需要初始化IIC的配置寄存器,此过程固件库已经帮忙封装成接口,我们只需要调用接口配置即可.我们需要深入了解底层原理,可通过STM32f407手册对照相关寄存器理解硬件电路.

  1. void I2C3_Init(void)
  2. {
  3.     GPIO_InitTypeDef  GPIO_InitStructure;
  4.     I2C_InitTypeDef I2C_InitStructure;
  5.     RCC_ClocksTypeDef   rcc_clocks;

  6.     /* GPIO Peripheral clock enable */
  7.     RCC_AHB1PeriphClockCmd(IIC_SDA_GPIO_CLK|IIC_SCL_GPIO_CLK, ENABLE);
  8.     /*i2c3 Peripheral clock enable */
  9.     RCC_APB1PeriphClockCmd(IIC_CLK, ENABLE);
  10.    

  11.     /*I2C3 configuration*/
  12.     GPIO_PinAFConfig(IIC_SDA_PORT, IIC_SDA_PINSOURCE, IIC_SDA_AF);
  13.     GPIO_PinAFConfig(IIC_SCL_PORT, IIC_SCL_PINSOURCE, IIC_SCL_AF);

  14.     // Pc9: I2C_SDA
  15.     GPIO_InitStructure.GPIO_Pin = IIC_SDA_PIN;
  16.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
  17.     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
  18.     GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
  19.     GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_UP;
  20.     GPIO_Init(IIC_SDA_PORT, &GPIO_InitStructure);

  21.         //PA8: I2C_SCL
  22.     GPIO_InitStructure.GPIO_Pin = IIC_SCL_PIN;
  23.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
  24.     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
  25.     GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
  26.     GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_UP;
  27.     GPIO_Init(IIC_SCL_PORT, &GPIO_InitStructure);

  28.     /* I2C Struct Initialize */
  29.     I2C_DeInit(IIC);
  30.     I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
  31.     I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
  32.     I2C_InitStructure.I2C_OwnAddress1 = 0x01;
  33.     I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
  34.     I2C_InitStructure.I2C_ClockSpeed = 50000;
  35.     I2C_InitStructure.I2C_AcknowledgedAddress =          I2C_AcknowledgedAddress_7bit;
  36.     I2C_Init(IIC, &I2C_InitStructure);

  37.     /* I2C Initialize */
  38.     I2C_Cmd(IIC, ENABLE);
  39.           I2C_AcknowledgeConfig(IIC, ENABLE);


  40. }




 楼主| 发给她更好fh 发表于 2023-3-29 12:36 | 显示全部楼层
2、MCP4017使用说明
2.1 电位器mcp4017地址.

  先看手册找到设备地址:

    1

545526423c05aab3b8.png
518146423c062301a1.png
从MCP4017手册中可以看到7位地址是0x27 ,不包括读写位.
 楼主| 发给她更好fh 发表于 2023-3-29 12:38 | 显示全部楼层
2.1 电位器mcp4017写时序.
245576423c0ba5c41c.png
从图可看到,主机通过IIC接口向MCP4017 写一个字节 时序: 从机地址+写命令+ 要写的数据.
 楼主| 发给她更好fh 发表于 2023-3-29 12:38 | 显示全部楼层
STM32F407作为主机写的代码如下所示:
以下代码经验证可以正常写数据到MCP4017.


  1. static uint32_t GetI2C3TimeLimit(void)
  2. {
  3.         RCC_ClocksTypeDef RCC_Clocks;
  4.         RCC_GetClocksFreq(&RCC_Clocks);
  5.         return RCC_Clocks.SYSCLK_Frequency/10000;
  6. }
  7. int32_t IIC3_WriteOneByte(uint8_t devAdder,  uint8_t value)
  8. {
  9.         uint32_t TimeLimit     = GetI2C3TimeLimit();
  10.         uint32_t Timetmp            = TimeLimit;
  11.        

  12.         while((--Timetmp)&&(I2C_GetFlagStatus(IIC, I2C_FLAG_BUSY)));
  13.         if(Timetmp == 0)
  14.                 return -1;//i2c busy
  15.          
  16.         I2C_GenerateSTART(IIC, ENABLE);
  17.         Timetmp            = TimeLimit;

  18.         while((--Timetmp)&&(!I2C_CheckEvent(IIC,I2C_EVENT_MASTER_MODE_SELECT)));//EV5

  19.         //while((--Timetmp)&&(I2C_GetFlagStatus(IIC, I2C_FLAG_SB) == RESET));//EV5  
  20.         if(Timetmp == 0)
  21.                 return -2;//i2c send start fail
  22.        
  23.         I2C_Send7bitAddress(IIC, devAdder, I2C_Direction_Transmitter);//
  24.         Timetmp            = TimeLimit;

  25.         //while((--Timetmp)&&(I2C_GetFlagStatus(IIC, I2C_FLAG_ADDR) == RESET));//EV6
  26.         while((--Timetmp)&&(!I2C_CheckEvent(IIC,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)));//EV6
  27.         if(Timetmp == 0)

  28.                 return -3;//i2c send address failed
  29.        
  30.        

  31.         I2C_SendData(IIC, value);
  32.         Timetmp            = TimeLimit;
  33.         while((--Timetmp)&&(!I2C_CheckEvent(IIC,I2C_EVENT_MASTER_BYTE_TRANSMITTED)));//
  34.         if(Timetmp == 0)
  35.                 return -6;//i2c send data failed
  36.        
  37.         //--SEND STOP
  38.         I2C_GenerateSTOP(IIC, ENABLE);
  39.         Timetmp            = TimeLimit;
  40.         while((--Timetmp)&&(I2C_GetFlagStatus(IIC, I2C_FLAG_BUSY)));
  41.        
  42.         return 1;
  43. }
 楼主| 发给她更好fh 发表于 2023-3-29 12:39 | 显示全部楼层
2.2 电位器mcp4017读时序.

946386423c0fd80925.png
从图可看到,主机通过IIC接口向MCP4017 读一个字节 时序: 从机地址+读命令 后从机返回读取的数据.
 楼主| 发给她更好fh 发表于 2023-3-29 12:40 | 显示全部楼层
STM32F407作为主机读的代码如下所示:

  1. int32_t IIC3_ReadOneByte(uint8_t devAdder, uint8_t *data) // is used  only  for mcp4017 read timing
  2. {
  3.     uint32_t TimeLimit     = GetI2C3TimeLimit();
  4.         uint32_t Timetmp            = TimeLimit;
  5.        
  6.         //--Whether the status is busy
  7.         while((--Timetmp)&&(I2C_GetFlagStatus(IIC, I2C_FLAG_BUSY)));
  8.         if(Timetmp == 0)
  9.                 return -1;//i2c busy
  10.        
  11.         I2C_GenerateSTART(IIC, ENABLE);//after send start bit ,automaticlly switch to master mod .
  12.         Timetmp            = TimeLimit;
  13.         while((--Timetmp)&&(!I2C_CheckEvent(IIC,I2C_EVENT_MASTER_MODE_SELECT)));// EV5 event
  14.         if(Timetmp == 0)
  15.                 return -6;//i2c reSend start fail
  16.        
  17.         //--send 7bit address (receive/read mod)
  18.         I2C_Send7bitAddress(IIC, devAdder, I2C_Direction_Receiver);//
  19.         Timetmp            = TimeLimit;
  20.         while((--Timetmp)&&(!I2C_CheckEvent(IIC,I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)));//EV6 event
  21.         if(Timetmp == 0)
  22.                 return -7;//i2c reSend address failed
  23.        
  24.         //--ready to receive
  25.         I2C_AcknowledgeConfig(IIC, DISABLE);//just receive one byte ,disable ACK
  26.         I2C_GenerateSTOP(IIC, ENABLE);
  27.         Timetmp            = TimeLimit;
  28.         while((--Timetmp)&&(!I2C_CheckEvent(IIC,I2C_EVENT_MASTER_BYTE_RECEIVED)));//EV7事件
  29.         if(Timetmp == 0)
  30.                 return -8;//i2c no received
  31.        
  32.        
  33.         *data = I2C_ReceiveData(IIC);//save data

  34.         //--ACK enable
  35.         I2C_AcknowledgeConfig(IIC, ENABLE);
  36.        
  37.         return 1;
  38. }
 楼主| 发给她更好fh 发表于 2023-3-29 12:50 | 显示全部楼层
3 注意事项

本项目使用的是MCP4017 不要和MCP40D17搞混了两者都属于数字电位器但是两者的读写时序不一样要注意对照相应的datasheet的时序去修改代码.否则会读写不成功.
总结

以上就是本人调试MCP4017的过程记录.如有错误望指出.
zhuhuis 发表于 2023-3-29 19:15 | 显示全部楼层
怎么可能
bqyj 发表于 2023-3-29 19:18 | 显示全部楼层
别打击楼主,万一真是他写的呢
jiahy 发表于 2023-3-29 19:20 | 显示全部楼层
你都说万一了,哈哈
Clyde011 发表于 2024-1-27 13:24 | 显示全部楼层

脉冲变压器的原/副边相位关系,
万图 发表于 2024-1-27 15:20 | 显示全部楼层

还有另一种技术正在变得普遍
Uriah 发表于 2024-1-27 16:23 | 显示全部楼层

测试结果可能包括输出电压和电流、电压波浪、效率、负载能力等指标
Uriah 发表于 2024-1-27 16:23 | 显示全部楼层

测试结果可能包括输出电压和电流、电压波浪、效率、负载能力等指标
您需要登录后才可以回帖 登录 | 注册

本版积分规则

43

主题

563

帖子

1

粉丝
快速回复 在线客服 返回列表 返回顶部