MCP4725使用STM32硬件I2C(附代码)

先上I2C初始化。
头文件`

#ifndef _I2C_H_
#define _I2C_H_
#include "stm32f10x.h"
#include "rtthread.h"
#include <stdbool.h>

/**************************I2C参数定义,I2C1或I2C2********************************/
#define             I2Cx 				                        I2C1
#define             I2C_APBxClock_FUN                   RCC_APB1PeriphClockCmd
#define             I2C_CLK                             RCC_APB1Periph_I2C1
#define             I2C_GPIO_APBxClock_FUN              RCC_APB2PeriphClockCmd
#define             I2C_GPIO_CLK                        RCC_APB2Periph_GPIOB     
#define             I2C_SCL_PORT                        GPIOB   
#define             I2C_SCL_PIN                         GPIO_Pin_6
#define             I2C_SDA_PORT                        GPIOB 
#define             I2C_SDA_PIN                         GPIO_Pin_7

/* STM32 I2C 快速模式 */
#define I2C_Speed              100000  //*

/* 这个地址只要与STM32外挂的I2C器件地址不一样即可 */
#define I2Cx_OWN_ADDRESS7      0X0A   

#define MCP4725_ADDR					 0x60//MCP4725默认地址


void I2C1_Init(void);
void I2C_WriteDAC(uint16_t data,bool mod);
#endif //_I2C_H_

#include "./I2C/i2c.h"


/**
  * @brief  I2C I/O配置
  * @param  无
  * @retval 无
  */
static void I2C_GPIO_Config(void)
{
  GPIO_InitTypeDef  GPIO_InitStructure; 

	/* 使能与 I2C 有关的时钟 */
	
	I2C_GPIO_APBxClock_FUN ( I2C_GPIO_CLK, ENABLE );
	I2C_APBxClock_FUN ( I2C_CLK, ENABLE );
	
    
  /* I2C_SCL、I2C_SDA*/
  GPIO_InitStructure.GPIO_Pin = I2C_SCL_PIN;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;	       // 开漏输出
  GPIO_Init(I2C_SCL_PORT, &GPIO_InitStructure);
	
  GPIO_InitStructure.GPIO_Pin = I2C_SDA_PIN;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;	       // 开漏输出
  GPIO_Init(I2C_SDA_PORT, &GPIO_InitStructure);	
	
	
}


/**
  * @brief  I2C 工作模式配置
  * @param  无
  * @retval 无
  */
static void I2C_Mode_Configu(void)
{
  I2C_InitTypeDef  I2C_InitStructure; 

  /* I2C 配置 */
  I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
	
	/* 高电平数据稳定,低电平数据变化 SCL 时钟线的占空比 */
  I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
	
  I2C_InitStructure.I2C_OwnAddress1 =I2Cx_OWN_ADDRESS7; 
  I2C_InitStructure.I2C_Ack = I2C_Ack_Enable ;
	 
	/* I2C的寻址模式 */
  I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
	
	/* 通信速率 */
  I2C_InitStructure.I2C_ClockSpeed = I2C_Speed;
  
	/* I2C 初始化 */
  I2C_Init(I2Cx, &I2C_InitStructure);
  
	/* 使能 I2C */
  I2C_Cmd(I2Cx, ENABLE);   
}

/**
  * @brief  I2C 外设(EEPROM)初始化
  * @param  无
  * @retval 无
  */
void I2C1_Init(void)
{

  I2C_GPIO_Config(); 
 
  I2C_Mode_Configu();
}

写入dac值函数

/*********************************************
*							写DAC模块寄存器								 *
*参数1:写入值(0-4095,0为0V电压,4095为100% *
VDD电压)																		 *
*参数2:true-快速模式(不写入EEPROM),false-*
标准模式(写入EEPROM)即首次上电从EEPROM中读 *
取值。																			 *
*返回值:无																	 *
*********************************************/
void I2C_WriteDAC(uint16_t data,bool mod)
{
	if(data>4095)
		data=4095;
	
  while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY));
	
	I2C_GenerateSTART(I2C1, ENABLE);//开启I2C1
	while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));/*EV5,主模式*/

	I2C_Send7bitAddress(I2C1,  MCP4725_ADDR<<1 , I2C_Direction_Transmitter);//MCP4725器件地址 -- 默认0x60
	
	if(mod)//判断是否是快速模式,即只写DAC寄存器不写入EEPROM
	{
		while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));

		I2C_SendData(I2C1, (data&0xf00)>>8);//取出高四位
		while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));

		I2C_SendData(I2C1, data&0xff);//发送数据
		while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));

	}
	else//标准模式
	{
		while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));

		I2C_SendData(I2C1, 64);//64代表写寄存器
		while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));

		I2C_SendData(I2C1, data>>4);//发送数据
		while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
		
		I2C_SendData(I2C1, (data&15)<<4);//发送数据
		while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
	}
	
	I2C_GenerateSTOP(I2C1, ENABLE);//关闭I2C1总线

}

厂家只给了arduino的例程

#include <Wire.h>//Include the Wire library to talk I2C

//This is the I2C Address of the MCP4725, by default (A0 pulled to GND).
//Please note that this breakout is for the MCP4725A0. 
#define MCP4725_ADDR 0x60   
//For devices with A0 pulled HIGH, use 0x61

//Sinewave Tables were generated using this calculator:
//http://www.daycounter.com/Calculators/Sine-Generator-Calculator.phtml


int lookup = 0;//varaible for navigating through the tables

int sintab2[512] = 
{
  2048, 2073, 2098, 2123, 2148, 2174, 2199, 2224,
  2249, 2274, 2299, 2324, 2349, 2373, 2398, 2423,
  2448, 2472, 2497, 2521, 2546, 2570, 2594, 2618,
  2643, 2667, 2690, 2714, 2738, 2762, 2785, 2808,
  2832, 2855, 2878, 2901, 2924, 2946, 2969, 2991,
  3013, 3036, 3057, 3079, 3101, 3122, 3144, 3165,
  3186, 3207, 3227, 3248, 3268, 3288, 3308, 3328,
  3347, 3367, 3386, 3405, 3423, 3442, 3460, 3478,
  3496, 3514, 3531, 3548, 3565, 3582, 3599, 3615,
  3631, 3647, 3663, 3678, 3693, 3708, 3722, 3737,
  3751, 3765, 3778, 3792, 3805, 3817, 3830, 3842,
  3854, 3866, 3877, 3888, 3899, 3910, 3920, 3930,
  3940, 3950, 3959, 3968, 3976, 3985, 3993, 4000,
  4008, 4015, 4022, 4028, 4035, 4041, 4046, 4052,
  4057, 4061, 4066, 4070, 4074, 4077, 4081, 4084,
  4086, 4088, 4090, 4092, 4094, 4095, 4095, 4095,
  4095, 4095, 4095, 4095, 4094, 4092, 4090, 4088,
  4086, 4084, 4081, 4077, 4074, 4070, 4066, 4061,
  4057, 4052, 4046, 4041, 4035, 4028, 4022, 4015,
  4008, 4000, 3993, 3985, 3976, 3968, 3959, 3950,
  3940, 3930, 3920, 3910, 3899, 3888, 3877, 3866,
  3854, 3842, 3830, 3817, 3805, 3792, 3778, 3765,
  3751, 3737, 3722, 3708, 3693, 3678, 3663, 3647,
  3631, 3615, 3599, 3582, 3565, 3548, 3531, 3514,
  3496, 3478, 3460, 3442, 3423, 3405, 3386, 3367,
  3347, 3328, 3308, 3288, 3268, 3248, 3227, 3207,
  3186, 3165, 3144, 3122, 3101, 3079, 3057, 3036,
  3013, 2991, 2969, 2946, 2924, 2901, 2878, 2855,
  2832, 2808, 2785, 2762, 2738, 2714, 2690, 2667,
  2643, 2618, 2594, 2570, 2546, 2521, 2497, 2472,
  2448, 2423, 2398, 2373, 2349, 2324, 2299, 2274,
  2249, 2224, 2199, 2174, 2148, 2123, 2098, 2073,
  2048, 2023, 1998, 1973, 1948, 1922, 1897, 1872,
  1847, 1822, 1797, 1772, 1747, 1723, 1698, 1673,
  1648, 1624, 1599, 1575, 1550, 1526, 1502, 1478,
  1453, 1429, 1406, 1382, 1358, 1334, 1311, 1288,
  1264, 1241, 1218, 1195, 1172, 1150, 1127, 1105,
  1083, 1060, 1039, 1017,  995,  974,  952,  931,
   910,  889,  869,  848,  828,  808,  788,  768,
   749,  729,  710,  691,  673,  654,  636,  618,
   600,  582,  565,  548,  531,  514,  497,  481,
   465,  449,  433,  418,  403,  388,  374,  359,
   345,  331,  318,  304,  291,  279,  266,  254,
   242,  230,  219,  208,  197,  186,  176,  166,
   156,  146,  137,  128,  120,  111,  103,   96,
    88,   81,   74,   68,   61,   55,   50,   44,
    39,   35,   30,   26,   22,   19,   15,   12,
    10,    8,    6,    4,    2,    1,    1,    0,
     0,    0,    1,    1,    2,    4,    6,    8,
    10,   12,   15,   19,   22,   26,   30,   35,
    39,   44,   50,   55,   61,   68,   74,   81,
    88,   96,  103,  111,  120,  128,  137,  146,
   156,  166,  176,  186,  197,  208,  219,  230,
   242,  254,  266,  279,  291,  304,  318,  331,
   345,  359,  374,  388,  403,  418,  433,  449,
   465,  481,  497,  514,  531,  548,  565,  582,
   600,  618,  636,  654,  673,  691,  710,  729,
   749,  768,  788,  808,  828,  848,  869,  889,
   910,  931,  952,  974,  995, 1017, 1039, 1060,
  1083, 1105, 1127, 1150, 1172, 1195, 1218, 1241,
  1264, 1288, 1311, 1334, 1358, 1382, 1406, 1429,
  1453, 1478, 1502, 1526, 1550, 1575, 1599, 1624,
  1648, 1673, 1698, 1723, 1747, 1772, 1797, 1822,
  1847, 1872, 1897, 1922, 1948, 1973, 1998, 2023
};


void setup()
{
  Wire.begin();

  // Set A2 and A3 as Outputs to make them our GND and Vcc,
  //which will power the MCP4725
  pinMode(A2, OUTPUT);
  pinMode(A3, OUTPUT);

  digitalWrite(A2, LOW);//Set A2 as GND
  digitalWrite(A3, HIGH);//Set A3 as Vcc
}
//---------------------------------------------------
void loop()
{
  Wire.beginTransmission(MCP4725_ADDR);
  Wire.write(64);                     // cmd to update the DAC
  Wire.write(2048 >> 4);        // the 8 most significant bits...
  Wire.write((2048 & 15) << 4); // the 4 least significant bits...
  Wire.endTransmission();
  lookup = (lookup + 1) & 511;
}

我一开始照着arduino的例程写stm32发现不行,会卡死在I2C的EV6事件,怎么调试都不行
几乎所有方法都试过之后无从下手了,然后来看arduino的I2C底层配置最终找到了原因`

void TwoWire::beginTransmission(uint8_t address)
{
  // indicate that we are transmitting
  transmitting = 1;
  // set address of targeted slave
  txAddress = address << 1;
  // reset tx buffer iterator vars
  txBufferIndex = 0;
  txBufferLength = 0;
}

原因在这txAddress = address << 1;行代码,把器件地址左移了一位,而我却是直接发送MCP4725的地址,最后在发送时左移1位就解决。然后昨天想在论坛上找个STM32硬件I2C控制MCP4725的代码参考一下自己错在哪,居然全都要钱下载,于是乎就贴上自己已经测试成功的代码给各位参考。

  • 26
    点赞
  • 61
    收藏
    觉得还不错? 一键收藏
  • 12
    评论
MCP4725是一种数字模拟转换器(DAC),可以将数字信号转换为模拟电压输出。下面是使用STM32驱动MCP4725的步骤: 1. 首先,需要将STM32MCP4725连接。可以使用I2C总线进行连接,将SCL连接到STM32的SCL引脚,SDA连接到STM32的SDA引脚,以及将MCP4725的VCC引脚连接到3.3V电源,GND引脚连接到STM32的地引脚。 2. 在STM32中,需要配置I2C总线。可以使用STM32提供的HAL库进行配置。例如,可以使用下面的代码初始化I2C1总线: ``` I2C_HandleTypeDef hi2c1; void MX_I2C1_Init(void) { hi2c1.Instance = I2C1; hi2c1.Init.ClockSpeed = 400000; hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2; hi2c1.Init.OwnAddress1 = 0; hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT; hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE; hi2c1.Init.OwnAddress2 = 0; hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE; hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE; if (HAL_I2C_Init(&hi2c1) != HAL_OK) { Error_Handler(); } } ``` 3. 然后,需要编写代码来设置MCP4725输出电压。可以使用下面的代码将输出电压设置为2.5V: ``` #define MCP4725_ADDR (0xC0 >> 1) void MCP4725_SetVoltage(float voltage) { uint16_t value = voltage / 3.3 * 4095; uint8_t data[3]; data[0] = (value >> 8) & 0x0F; data[1] = value & 0xFF; data[2] = (1 << 4) | (0 << 3); // Gain = 1x, Output Buffer Enabled HAL_I2C_Master_Transmit(&hi2c1, MCP4725_ADDR, data, 3, 100); } ``` 这个函数将会把电压值转换为一个12位的值,并且将其写入到MCP4725的寄存器中,从而设置输出电压。需要注意的是,这个函数假定MCP4725的地址为0xC0。 4. 最后,在主函数中调用MCP4725_SetVoltage函数来设置输出电压。例如,可以使用下面的代码将输出电压设置为2.5V: ``` int main(void) { HAL_Init(); MX_I2C1_Init(); while (1) { MCP4725_SetVoltage(2.5); HAL_Delay(1000); } } ``` 这个代码将会每隔1秒钟将MCP4725的输出电压设置为2.5V。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值