使用HAL库硬件I2C时如何设置器件地址?
我使用的模块是包含了DS1307的AT24C32两个I2C通讯的芯片,开始准备启用硬件I2C,但测试了多天都没有成功,后来只要改为GPIO模拟I2C才成功驱动这两个芯片。现在我仍想继续尝试用硬件I2C,但一直不知道如何在操作前设定器件的地址,我使用的是HAL库,在此请各位指教,谢谢!是指设置从地址码?
/* I2C1 init function */
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();
}
}
还是访问器件的地址?
HAL_I2C_Mem_Write(&hi2c1,ADDRESS,DC,I2C_MEMADD_SIZE_8BIT,&Byte,1,I2C_TIMEOUT);
谢谢回复!是从器件的地址。
那是不是每次读写不同的器件之前都要调用I2C_Init()函数? 使用库函数读写的时候就能设置地址,不需要初始化那里设置,HAL_I2C_Mem_Read(i2c_handler, Addr, (uint16_t)Reg, I2C_MEMADD_SIZE_8BIT, Buffer, Length, 1000);可以看到第二哥参数是设备地址,第三个就是寄存器地址。 morphlings2014 发表于 2019-9-19 09:30
使用库函数读写的时候就能设置地址,不需要初始化那里设置,HAL_I2C_Mem_Read(i2c_handler, Addr, (uint16_ ...
谢谢指教,在再试试看。 参考代码如下,我测试没有问题的。DS1307
uint8_t data1,data;
uint8_t ch;
ch = 0x00;
if(HAL_I2C_Master_Transmit(&hi2c1,0xD0,(uint8_t*)&ch,1,10000) != HAL_OK)
{
return;
}
if(HAL_I2C_Master_Receive(&hi2c1,0xD0,data1,7,10000) != HAL_OK)
{
return;
}
按照四楼老师的提示使用HAL_I2C_Mem_Read()函数似乎可以读出数据了,但不知为何,读出的第一个数据没有问题,而后面的数据则不正确,还在继续测试中。下面是读数据时的时序图:
发出器件地址和内存地址的时序是正确的
连续读入了7个字节的数据
但读入的数据却不同于DS1307内存数据,DS1307中有时间和日期数据,而读出的却只是1或0.
这是读连续7个字节的时序图
读写DS1307的函数如下:
/******************************************************************************************
* 函数名称: DS1307_I2C_Read()
* 功能说明: 读DS1307的日历数据,并转换为各自的变量值
* 输 入: 无
* 输 出: 0 = 成功从DS1307获取数据>0 = 从DS1307获取数据过程中出现错误
******************************************************************************************/
void DS1307_I2C_Read(void)
{
while (HAL_I2C_Mem_Read(&hi2c1,0x00D0,0,I2C_MEMADD_SIZE_8BIT,(uint8_t*)DS_Buff,7,10000) != HAL_OK)
// while (HAL_I2C_Master_Receive(&hi2c1, 0, (uint8_t *)DS_Buff, 7, 10000) != HAL_OK)
{
if (HAL_I2C_GetError(&hi2c1) != HAL_I2C_ERROR_AF)
{
LCD_write_ASCII(0,3,1,(uint8_t *)"DS_Read_Error!");
}
}
second = ((DS_Buff&0x70)>>4)*10 + (DS_Buff&0x0F);//秒,屏蔽秒的第7位的标志
minute = ((DS_Buff&0x70)>>4)*10 + (DS_Buff&0x0F);//分(取低7位)
hour = ((DS_Buff&0x30)>>4)*10 + (DS_Buff&0x0F);//时(取低5位)
week = (DS_Buff&0x07); //周(取低3位)
day = ((DS_Buff&0x30)>>4)*10 + (DS_Buff&0x0F); //日(取低6位)
month = ((DS_Buff&0x10)>>4)*10 + (DS_Buff&0x0F); //月(取低5位)
year = 2000 + (DS_Buff>>4)*10 + (DS_Buff&0x0F);//年
}
/******************************************************************************************
* 函数名称: DS1307_I2C_Write()
* 功能说明: 将当前的日历数据写入DS1307
* 输 入: 无
* 输 出: 0 = 成功写入数据>0 = DS1307写入数据过程中出现错误
******************************************************************************************/
void DS1307_I2C_Write(void)
{
uint8_t temp;
DS_Buff = 0; //秒
temp = ((minute/10)<<4|(minute%10));
DS_Buff = temp; //分
temp = ((hour/10)<<4|(hour%10));
DS_Buff = temp; //时
DS_Buff = week; //星期
temp = ((day/10)<<4|(day%10));
DS_Buff = temp; //日
temp = ((month/10)<<4|(month%10));
DS_Buff = temp; //月
temp = ((year%100)/10<<4|(year%10));
DS_Buff = temp; //年
while (HAL_I2C_Mem_Write(&hi2c1,0x00D0,0,I2C_MEMADD_SIZE_8BIT,(uint8_t*)DS_Buff,7,10000) != HAL_OK)
// while (HAL_I2C_Master_Transmit(&hi2c1, 0, (uint8_t *)DS_Buff, 7, 10000) != HAL_OK)
{
if (HAL_I2C_GetError(&hi2c1) != HAL_I2C_ERROR_AF)
{
LCD_write_ASCII(0,3,1,(uint8_t *)"DS_Write_Erro!");
// return 2;
}
}
// return 0;
}
从图上看,读时序似乎没有问题。
你看一下你的写时序逻辑是什么要样的吧 安 发表于 2019-9-19 11:19
参考代码如下,我测试没有问题的。DS1307
uint8_t data1,data;
uint8_t c ...
按照您的代码示例,确实能够对DS1307进行读写操作,不知为何我原来用这个函数时,这个参数却出现在第2个字节,第1个字节是0xF0(见下图):
第一个字节是0xF0,第二个字节才是地址参数0xD0,以至于我以为这个地址参数是要读取的内存地址呢。
下面是一个完整的读出7个字节内容的时序:
这是放大后的时序:
这是读出的内容:
从目前测试的情况看,用HAL_I2C_Receive()和HAL_I2C_Transmit()函数对DS1307进行操作是没有问题了,但用HAL_I2C_Mem_Read()和HAL_I2C_Mem_Write()函数对DS1307进行操作却还存在问题,还需要继续测试排错。
另外有个疑问:用HAL_I2C_Receive()和HAL_I2C_Transmit()函数是不是只能从0字节开始读写操作,不能对某个指定的字节进行操作?
下面是分别用HAL_I2C_Receive()和HAL_I2C_Transmit()函数,HAL_I2C_Mem_Read()和HAL_I2C_Mem_Write()函数对DS1307进行操作的函数:
/******************************************************************************************
* 函数名称: DS1307_I2C_Transmit(uint8_t size)
* 功能说明: 写数据到DS1307
* 输 入: size 数据个数(要写入数据在全局数组DS_Buff中)
* 输 出: 0 = 成功写入1 = 写数据过程中出现错误
******************************************************************************************/
uint8_t DS1307_I2C_Transmit(uint8_t size)
{
DS1307_DataToBuff(); //将时间及日期数据转换到Buff数组中
if(HAL_I2C_Master_Transmit(&hi2c1,0xD0,(uint8_t*)DS_Buff ,size,10000) != HAL_OK)
{
return 1;
}
return 0;
}
/******************************************************************************************
* 函数名称: DS1307_I2C_Receive(uint8_t size)
* 功能说明: 从DS1307读出数据
* 输 入: size 数据个数(读出的数据在全局数组DS_Buff中)
* 输 出: 0 = 成功读出1 = 读数据过程中出现错误
******************************************************************************************/
uint8_t DS1307_I2C_Receive(uint8_t size)
{
if(HAL_I2C_Master_Receive(&hi2c1,0xD0,DS_Buff,7,10000) != HAL_OK)
{
return 1;
}
if(size == 1){ //检查DS1307是否需要初始化
if(DS_Buff>127){
year = 2019;
month = 9;
day = 18;
week = 3;
hour = 9;
minute = 1;
DS1307_DataToBuff();
DS1307_I2C_Transmit(8);
}
}
else{
DS1307_BuffToData();
}
return 0;
}
/******************************************************************************************
* 函数名称: DS1307_I2C_Read()
* 功能说明: 读DS1307的日历数据,并转换为各自的变量值
* 输 入: 无
* 输 出: 0 = 成功从DS1307获取数据>0 = 从DS1307获取数据过程中出现错误
******************************************************************************************/
void DS1307_I2C_Read(void)
{
while (HAL_I2C_Mem_Read(&hi2c1,0x00D0,0,I2C_MEMADD_SIZE_8BIT,(uint8_t*)DS_Buff,7,10000) != HAL_OK)
// while (HAL_I2C_Master_Receive(&hi2c1, 0, (uint8_t *)DS_Buff, 7, 10000) != HAL_OK)
{
if (HAL_I2C_GetError(&hi2c1) != HAL_I2C_ERROR_AF)
{
LCD_write_ASCII(0,3,1,(uint8_t *)"DS_Read_Error!");
}
}
DS1307_BuffToData();
}
/******************************************************************************************
* 函数名称: DS1307_I2C_Write()
* 功能说明: 将当前的日历数据写入DS1307
* 输 入: 无
* 输 出: 0 = 成功写入数据>0 = DS1307写入数据过程中出现错误
******************************************************************************************/
void DS1307_I2C_Write(void)
{
DS1307_DataToBuff(); //时间日期数据转换存入Buff数组中
while (HAL_I2C_Mem_Write(&hi2c1,0x00D0,0,I2C_MEMADD_SIZE_8BIT,(uint8_t*)DS_Buff,7,10000) != HAL_OK)
// while (HAL_I2C_Master_Transmit(&hi2c1, 0, (uint8_t *)DS_Buff, 7, 10000) != HAL_OK)
{
if (HAL_I2C_GetError(&hi2c1) != HAL_I2C_ERROR_AF)
{
LCD_write_ASCII(0,3,1,(uint8_t *)"DS_Write_Erro!");
// return 2;
}
}
// return 0;
}
/******************************************************************************************
* 函数名称: DS1307_Chick()
* 功能说明: 检查DS1307是否已经初始化,若未初始化则用特写日期进行初始化
* 输 入: 无
* 输 出: 无
******************************************************************************************/
void DS1307_Check(void)
{
// LCD_write_ASCII(0,3,1,(uint8_t *)"Check_Begin...");
while (HAL_I2C_Mem_Read(&hi2c1,0x00D0,0,I2C_MEMADD_SIZE_8BIT,(uint8_t*)DS_Buff,1,10000) != HAL_OK)
while (HAL_I2C_Master_Receive(&hi2c1, 0, (uint8_t *)DS_Buff, 1, 10000) != HAL_OK)
{
if (HAL_I2C_GetError(&hi2c1) != HAL_I2C_ERROR_AF)
{
LCD_write_ASCII(0,3,1,(uint8_t *)"CheckReadErro!");
}
}
LCD_write_value(0,4,3,0,1,DS_Buff);
if(DS_Buff> 127){
year = 2019;
month = 9;
day = 18;
week = 3;
hour = 9;
minute = 1;
DS1307_DataToBuff();
while (HAL_I2C_Mem_Write(&hi2c1,0x00D0,0,I2C_MEMADD_SIZE_8BIT,(uint8_t*)DS_Buff,1,10000) != HAL_OK)
// while (HAL_I2C_Master_Transmit(&hi2c1, 0, (uint8_t *)DS_Buff, 8, 10000) != HAL_OK)
{
if (HAL_I2C_GetError(&hi2c1) != HAL_I2C_ERROR_AF)
{
LCD_write_ASCII(0,3,1,(uint8_t *)"CheckWriteErr!");
}
}
}
}
/******************************************************************************************
* 函数名称: DS1307_DataToBuff()
* 功能说明: 将时间日期变量数据转换到数组Buff中
* 输 入: 无
* 输 出: 无
******************************************************************************************/
void DS1307_DataToBuff(void)
{
uint8_t temp;
DS_Buff = 0; //秒
temp = ((minute/10)<<4|(minute%10));
DS_Buff = temp; //分
temp = ((hour/10)<<4|(hour%10));
DS_Buff = temp; //时
DS_Buff = week; //星期
temp = ((day/10)<<4|(day%10));
DS_Buff = temp; //日
temp = ((month/10)<<4|(month%10));
DS_Buff = temp; //月
temp = ((year%100)/10<<4|(year%10));
DS_Buff = temp; //年
DS_Buff = 32; //0010 0000 = 允许按1Hz输出方波
}
/******************************************************************************************
* 函数名称: DS1307_BuffToData()
* 功能说明: 将数组Buff数据转换到时间日期变量中
* 输 入: 无
* 输 出: 无
******************************************************************************************/
void DS1307_BuffToData(void)
{
second = ((DS_Buff&0x70)>>4)*10 + (DS_Buff&0x0F);//秒,屏蔽秒的第7位的标志
minute = ((DS_Buff&0x70)>>4)*10 + (DS_Buff&0x0F);//分(取低7位)
hour = ((DS_Buff&0x30)>>4)*10 + (DS_Buff&0x0F);//时(取低5位)
week = (DS_Buff&0x07); //周(取低3位)
day = ((DS_Buff&0x30)>>4)*10 + (DS_Buff&0x0F); //日(取低6位)
month = ((DS_Buff&0x10)>>4)*10 + (DS_Buff&0x0F); //月(取低5位)
year = 2000 + (DS_Buff>>4)*10 + (DS_Buff&0x0F);//年
}
页:
[1]
2