2229|0

23

帖子

0

TA的资源

一粒金砂(中级)

楼主
 

【雅特力AT-START-F435】I2C读取AS5600角度数据 [复制链接]

  本帖最后由 hitwpc 于 2023-7-11 02:14 编辑
本次测评中参考例程中I2C,获取无刷电机实时角度位置,并使用串口将数据信息通过VOFA进行实时波形显示。

参考文件目录如下:

AT32F435_437_Firmware_Library_V2.1.2\project\at_start_f435\examples\i2c\communication_int

参考AS5600驱动开源链接:

链接已隐藏,如需查看请登录或者注册

IIC的基础原理

参考大佬Z小旋的教程,对I2C的物理层、协议层、时序图都做了很好的解释,如果单片机作为主机去读取从机的信息,完全足够,可以参考下面的文章。

(71条消息) IIC原理超详细讲解---值得一看_Z小旋的博客-CSDN博客

程序介绍

官方例程I2C参考

首先查看库函数(文件at32f435437i2c.c),可以看到里面的的库函数还是比较底层的,如获取地址,操作数据寄存器直接发送数据。如果认真观看了IIC的基础原理,就会发现,IIC的时许和逻辑较为复杂,此类底层函数库是不能完成IIC的发送和读取数据的。

碰巧官方例程(AT32F435_437_Firmware_Library_V2.1.2\project\at_start_f435\examples\i2c\communication_int)中完善了IIC相关的驱动函数,文件为i2c_application.c。

因此我们首先把该文件的函数都拷走,下面我们将主要用到这个函数

i2c_status_type i2c_memory_read(i2c_handle_type* hi2c, i2c_mem_address_width_type mem_address_width, uint16_t address, uint16_t mem_address, uint8_t* pdata, uint16_t size, uint32_t timeout)

可以实现使用指定I2C,向指定从机地址的内存地址读取指定长度的数据(STM32的HAL库中有类似的函数)。

下面看下函数内部的实现逻辑

①等待检测I2C是否忙碌

②发送启动信号,同时发送从机地址

③等待检测发送从机地址的ACK信号是否收到

④发送需要读取的内存地址

⑤等待检测是否发送完成

⑥发送启动信号,同时发送从机地址

⑦等待检测发送从机地址的ACK信号是否收到

⑧循环读取指定长度的数据

从这个过程中,我们可以看到读取的过程是②发送从机地址、④发送内存地址、⑥发送从机地址、⑧读取指定内存的数据,其余过程都在校验上一步是否完成。校验函数的形式如下:

i2c_wait_flag(hi2c, I2C_TCRLD_FLAG, I2C_EVENT_CHECK_NONE, timeout)

里面有timeout超时机制,因此I2C的发送失败(或者示波器根本抓不到发出的波形),可以尝试调大timeout值(本人在实验过程中,timeout0XFF时会发送失败,0XFFF则发送成功)。

源码如下:

i2c_status_type i2c_memory_read(i2c_handle_type* hi2c, i2c_mem_address_width_type mem_address_width, uint16_t address, uint16_t mem_address, uint8_t* pdata, uint16_t size, uint32_t timeout)

{

/* initialization parameters */

hi2c->pbuff = pdata;

hi2c->pcount = size;

hi2c->error_code = I2C_OK;

/* wait for the busy flag to be reset */

if (i2c_wait_flag(hi2c, I2C_BUSYF_FLAG, I2C_EVENT_CHECK_NONE, timeout) != I2C_OK)

{

return I2C_ERR_STEP_1;

}

/* start transfer */

i2c_transmit_set(hi2c->i2cx, address << 1, mem_address_width, I2C_SOFT_STOP_MODE, I2C_GEN_START_WRITE);

//i2c_start_transfer(hi2c, address<<1, I2C_GEN_START_WRITE);

/* wait for the tdis flag to be set */

if (i2c_wait_flag(hi2c, I2C_TDIS_FLAG, I2C_EVENT_CHECK_ACKFAIL, timeout) != I2C_OK)

{

return I2C_ERR_STEP_2;

}

/* send memory address */

if (i2c_memory_address_send(hi2c, mem_address_width, mem_address, timeout) != I2C_OK)

{

return I2C_ERR_STEP_3;

}

/* wait for the tdc flag to be set */

if (i2c_wait_flag(hi2c, I2C_TDC_FLAG, I2C_EVENT_CHECK_NONE, timeout) != I2C_OK)

{

return I2C_ERR_STEP_4;

}

/* start transfer */

i2c_start_transfer(hi2c, address<<1, I2C_GEN_START_READ);

while (hi2c->pcount > 0)

{

/* wait for the rdbf flag to be set */

if (i2c_wait_flag(hi2c, I2C_RDBF_FLAG, I2C_EVENT_CHECK_ACKFAIL, timeout) != I2C_OK)

{

return I2C_ERR_STEP_5;

}

/* read data */

(*hi2c->pbuff++) = i2c_data_receive(hi2c->i2cx);

hi2c->pcount--;

hi2c->psize--;

if ((hi2c->psize == 0) && (hi2c->pcount != 0))

{

/* wait for the tcrld flag to be set */

if (i2c_wait_flag(hi2c, I2C_TCRLD_FLAG, I2C_EVENT_CHECK_NONE, timeout) != I2C_OK)

{

return I2C_ERR_STEP_6;

}

/* continue transfer */

i2c_start_transfer(hi2c, address, I2C_WITHOUT_START);

}

}

/* wait for the stop flag to be set */

if (i2c_wait_flag(hi2c, I2C_STOPF_FLAG, I2C_EVENT_CHECK_ACKFAIL, timeout) != I2C_OK)

{

return I2C_ERR_STEP_7;

}

/* clear stop flag */

i2c_flag_clear(hi2c->i2cx, I2C_STOPF_FLAG);

/* reset ctrl2 register */

i2c_reset_ctrl2_register(hi2c);

return I2C_OK;

}

AS5600驱动

参考下面的代码

链接已隐藏,如需查看请登录或者注册

AS5600是一种易于编程的磁性旋转位置传感器,具有高分辨率12位模拟或PWM输出。该非接触系统测量轴上径向磁化磁体的绝对角度。AS5600专为无触点电位器应用而设计,其坚固的设计消除了任何均匀外部杂散磁场的影响。行业标准I²C接口支持非易失性参数的简单用户编程,无需专门的程序员。默认情况下,输出表示0到360度的范围。也可以通过编程零角度(开始位置)和最大角度(停止位置)来定义输出的较小范围。AS5600还配备了智能低功耗模式功能,可自动降低功耗。输入引脚(DIR)选择输出相对于旋转方向的极性。如果DIR接地,输出值随顺时针旋转而增加。如果DIR连接到VDD,则输出值随逆时针旋转而增加。LibDriver AS5600是LibDriver推出的AS5600全功能驱动,该驱动提供磁角度读取等功能并且它符合MISRA标准。

在以下函数接口中,添加自己的驱动函数

①初始化函数

uint8_t as5600_interface_iic_init(void)

{

hi2cx.i2cx = I2Cx_PORT;

/* i2c config */

i2c_config(&hi2cx);

return 0;

}

②I2C读取函数

uint8_t as5600_interface_iic_read(uint8_t addr, uint8_t reg, uint8_t *buf, uint16_t len)

{

i2c_memory_read(&hi2cx, I2C_MEM_ADDR_WIDIH_8,addr,reg,buf,len,0xFFF);

return 0;

}

③I2C写函数

uint8_t as5600_interface_iic_write(uint8_t addr, uint8_t reg, uint8_t *buf, uint16_t len)

{

i2c_memory_write(&hi2cx, I2C_MEM_ADDR_WIDIH_8,addr,reg,buf,len,0xFFF);

return 0;

}

④延时函数

void as5600_interface_delay_ms(uint32_t ms)

{

delay_ms(ms);

}

接下来主函数中,初始化阶段添加as5600_basic_init();

在主循环中添加 as5600_basic_read(float *angle),即可读取出AS5600的机械角度值(当然还需要电角度换算)。

在测试过程中,发现AT32F435I2C的发送从机地址时,需要将从机地址左移一位,然后在最低位(LSB)来判断时读还是写。需要手动改一下库函数

i2c_transmit_set(hi2c->i2cx, address << 1, mem_address_width, I2C_SOFT_STOP_MODE, I2C_GEN_START_WRITE);

实物测试效果

红色线为机械角度,绿色线为电角度(使用的无刷电机24N22P,是11对级,因此电角度是11倍的机械角度)。


20230711-010829

 

点赞 关注
 
 

回复
举报
您需要登录后才可以回帖 登录 | 注册

查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/8 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表