首页 > 其他分享 >ESP32 IDF 读取双路AS5600

ESP32 IDF 读取双路AS5600

时间:2023-06-01 23:22:18浏览次数:48  
标签:I2C AS5600 双路 ESP32 master IIC IDF i2c port

白了少年头,空悲切。
又有哥们生孩子了。他们有车有房有老婆还有孩子,也不知咋挣来的。搞得我聚会都不想去了。
郁闷。
没办法,自己只有努力。
胸藏万卷凭吞吐,笔有千钧任翕张。

前言

  • 之前用ESP32驱动两路AS5600没有成功,后面简单梳理了下IIC的逻辑,才反应过来。下面记录一下。

ESP32 IDF环境下双路IIC的切换读取

在官方提供的几个IIC的demo中,都是不做切换的读取。按照例程的步骤初始化单路IIC,读取时没问题。多路切换时,只需要注意切换 i2c_master_port 这个参数就行了。

首先,需要在初始化中分别注册两路IIC及其对应的引脚:

 esp_err_t i2c_master_init(void)
{

	 int i2c_master_port = I2C_AS5600_NUM0;  //这个port是切换IIC的关键,在i2c_driver_install中要注册不同的port

	     i2c_config_t conf = {
	         .mode = I2C_MODE_MASTER,
	         .sda_io_num = I2C_AS5600_SDA_0,
	         .sda_pullup_en = GPIO_PULLUP_ENABLE,
	 		.scl_io_num = I2C_AS5600_SCL_0,
	         .scl_pullup_en = GPIO_PULLUP_ENABLE,
	         .master.clk_speed = I2C_AS5600_FREQ_HZ,
	     };

	     i2c_param_config(i2c_master_port, &conf);

	     i2c_driver_install(i2c_master_port, conf.mode, I2C_AS5600_RX_BUF_DISABLE, I2C_AS5600_TX_BUF_DISABLE, 0);

	     i2c_master_port = I2C_AS5600_NUM1;//另一路IIC

	     i2c_config_t conf1 = {
	         .mode = I2C_MODE_MASTER,
	         .sda_io_num = I2C_AS5600_SDA_1,
	         .sda_pullup_en = GPIO_PULLUP_ENABLE,
	 		.scl_io_num = I2C_AS5600_SCL_1,
	         .scl_pullup_en = GPIO_PULLUP_ENABLE,
	         .master.clk_speed = I2C_AS5600_FREQ_HZ,
	     };

	     i2c_param_config(i2c_master_port, &conf1);

	     return i2c_driver_install(i2c_master_port, conf1.mode, I2C_AS5600_RX_BUF_DISABLE, I2C_AS5600_TX_BUF_DISABLE, 0);


}

然后在使用过程中,切换 i2c_master_port 参数就行了:


static  esp_err_t i2c_master_DataGet(uint8_t sensorNum,float *returnAngel){

	uint8_t angle_high = 0;
	    uint8_t angle_low = 0;
	    uint16_t result = 0;
	    float angle=0;
	    i2c_cmd_handle_t cmd;
	    int i2c_master_port = I2C_AS5600_NUM0;

	    if(sensorNum == 0){
	    	 i2c_master_port = I2C_AS5600_NUM0;//这个port是切换IIC的关键,读取时使用不同的port就能切换IIC
	    }else{
	    	i2c_master_port = I2C_AS5600_NUM1;
	    }
	    //读取HighAddr
	    cmd = i2c_cmd_link_create();
	    i2c_master_start(cmd);
	    i2c_master_write_byte(cmd, I2C_AS5600_SENSOR_ADDR << 1 | WRITE_BIT, ACK_CHECK_EN);
	    i2c_master_write_byte(cmd, I2C_AS5600_ANGLE_ADDRH, ACK_CHECK_EN);
	    i2c_master_stop(cmd);
	    i2c_master_cmd_begin(i2c_master_port, cmd, 10 / portTICK_PERIOD_MS);  //可以看到,上面的操作应该是需要这个begin开始启动,使用port来确认对哪个IIC进行操作
	    i2c_cmd_link_delete(cmd);
	    //vTaskDelay(1 / portTICK_PERIOD_MS);

	    cmd = i2c_cmd_link_create();
	    i2c_master_start(cmd);
	    i2c_master_write_byte(cmd, I2C_AS5600_SENSOR_ADDR << 1 | READ_BIT, ACK_CHECK_EN);
	    i2c_master_read_byte(cmd, &angle_high, ACK_VAL); //0x0c是高位
	    i2c_master_read_byte(cmd, &angle_low, NACK_VAL);
	    i2c_master_stop(cmd);
	    i2c_master_cmd_begin(i2c_master_port, cmd, 10 / portTICK_PERIOD_MS);
	    i2c_cmd_link_delete(cmd);

	    result=(uint16_t)(angle_high<<8|angle_low); //一共就11位 注意
	    angle=((int) result & 0b0000111111111111)*360.0/4096.0;
	    *returnAngel = angle;
	    //printf("angle%d: %.2f \n",sensorNum,angle);

return 0;
}

可以看到,IDF环境对于IIC的处理是将IIC的操作放到了 i2c_master_start()和 i2c_master_stop()之间,进行了类似队列的保存操作(没深入探究),然后是用i2c_master_cmd_begin()才开始 进行硬件上的操作,所以在此处切换不同的IIC端口。一开始没注意到此处,就想着前面怎么没有端口切换相关的参数呢。

剥离成中间函数

后面是用结构体来 模拟C++的类,进行函数封装。
首先在 .h文件中定义结构体函数,并定义需要的结构体函数,然后是用 extern 做全局定义:


struct cenAngleGetBasicStruct{
	uint8_t AngleSenserNum;
	int8_t	SensorMoveDir[2];		//电机运动方向,+1:正向,-1:负向,0:不动
	float AngelSingleTurn[2];		//单圈记录值,浮点数类型
	float AngelSingleTurnInit[2];	//单圈记录值,精确到0.01度,放大100倍,
	long double AngelMultiTurn[2];		//多圈圈记录角度值,精确到0.01度,放大100倍
	void (*cenAngleGetInit)(void);
	void (*cenAngleGet)(uint8_t sensorNum,float *returnAngle);

};

extern struct cenAngleGetBasicStruct cenAngleGetClass;  //全局使用的角度相关的结构体
void cenAngleGetClassInit(void);

然后在同名 .c 文件中进行赋值和函数绑定:

struct cenAngleGetBasicStruct cenAngleGetClass;  //全局使用的角度相关的结构体
/*------------------------------
*函数:cenAngleGetClassInit
*
*说明: 中间层的角度获取class初始化
*		需要在主函数之前调用一次本函数,用于仿class类的初始化绑定
*
*
*参数:
*
*
*编写:ZNZZ wcc 执念执战 2023-5-20
*
*修改:
------------------------------*/
void cenAngleGetClassInit(void){
	//初始化内部参数,设置默认参数
	cenAngleGetClass.AngleSenserNum = 2;
	cenAngleGetClass.AngelMultiTurn[0]=0;

	//绑定对应的函数形成方法
	cenAngleGetClass.cenAngleGetInit = basAS5600Init;
	cenAngleGetClass.cenAngleGet = basAS5600AngleGet;  //角度获取方法,在需要的地方调用即可
	//调用方法
	cenAngleGetClass.cenAngleGetInit();//调用Init方法来完成硬件初始化。
}


然后就能在其他地方包含 .h 头文件后使用了。这种方法能够较为简单的剥离底层和上层。实际上,将赋值这一步想办法实现为从bin地址中赋值为指定的函数地址,理论上就能实现更为复杂的类似驱动安装的效果,实现跨平台(当然,我没有深究过别人的跨平台是如何实现的,但是思路上应该差不多)。我后续的程序会尽可能的使用这种方式,将不同的功能都剥离成各自的仿类Class。这种方式写起来略显麻烦,因为都要多加一步中间的结构体层。

下面是在mian中的测试方法:

void app_main(void)
{
	int count = 0;
	float angle = 0.0;
	cenAngleGetClassInit();
	while(1){
		cenAngleGetClass.cenAngleGet(count%2,&angle);//实现两路IIC的快速切换读取
		printf("GetAngle %d:%.2f \n",count%2,angle);
		count++;
	}
}

总结

我看到还有很多用C语言模拟C++或是其他语言特性的写法,不过实现起来比较费时间,用起来也比较鸡肋。所以简单用一些比较好用的特性就够了,毕竟现在很多单片机的编译器都支持C++语法特性了,比如现在用的ESP32-IDF的开发环境就是支持C++语法的,只是需要简单配置。

最近变得好懒了,FOC好几周了,只是能让电机保持不动了,怎么让电机动起来还是不想搞。

  • 本文水平有限,内容很多词语由于知识水平问题不严谨或很离谱,但主要作为记录作用,希望以后的自己和路过的大神对必要的错误提出批评与指点,对可笑的错误请指出来,我会改正的。
  • 另外,转载使用请注明作者和出处,不要删除文档中的关于作者的注释。

随梦,随心,随愿,恒执念,为梦执战,执战苍天! ------------------执念执战

标签:I2C,AS5600,双路,ESP32,master,IIC,IDF,i2c,port
From: https://www.cnblogs.com/zhinianzhizhan/p/17450396.html

相关文章

  • MongoDB C++ gridfs worked example
    使用libmongoc,参考:http://mongoc.org/libmongoc/current/mongoc_gridfs_t.html#include<mongoc.h>#include<stdio.h>#include<stdlib.h>#include<fcntl.h>classMongoGridFS{public:MongoGridFS(constchar*db);~MongoGridFS();......
  • [ESP] ESP-IDF CLion构建
    报错信息xtensa-esp32-elf-gccisnotafullpathandwasnotfoundinthePATH.解决办法找到esp-idf的export.sh路径,如:/home/xxx/esp/esp-idf/export.sh打开CLion->Settings->Build,Execution,Deployment->Toolchain选项栏Environmentfile添加/home/xxx/......
  • 使用Arduino IDE对ESP32双核进行编程
    使用ArduinoIDE对ESP32双核进行编程 [复制链接]qrcodeESP32 FreeRTOS查看: 22988 | 回复: 0风筝 发表于:2020-1-1722:23:45|只看该作者|只看大图|倒序浏览楼主 ESP模块因其Wi-Fi功能(如ESP8266、ESP-12E等)而广受欢迎。这些都是......
  • [ESP] ESP-IDF WiFi配网(SoftAP+HTTPD)代码备注
    ESP-IDFWiFi配网(SoftAP+HTTPD)代码备注主要是为了方便了解实际代码层面的配网协议是什么样的,所以文档记录的基本上是代码片段。ESP-IDF的版本是V5.0使用SoftAP传输时,为了允许服务发现,必须在开始配置之前初始化mDNS。protocomm_security一共有3个选项,这里只说了protoco......
  • arduino esp32 ds18b20 实例代码
    #include<OneWire.h>#include<DallasTemperature.h>//引脚定义#defineONE_WIRE_BUS15//库引用实例OneWireoneWire(ONE_WIRE_BUS);DallasTemperaturesensors(&oneWire);voidsetup(void){Serial.begin(9600);sensors.begin();}voidloop(vo......
  • esp32c3 刷入 ESPHome 固件并联动 Home Assistant
    在物联网里有一个很有名的固件叫做ESPHome,它是一个通过简单而强大的配置文件控制ESP8266/ESP32并通过家庭自动化系统远程控制。目标这里通过一个简单的案例场景来开始讲述整个过程,目标是通过温湿度传感器上传室内温度并在墨水屏上展示温度变化曲线。先决条件既然是esp32......
  • 【Swift 开发】IDFA存储到钥匙串中保证永久不变,除非系统重装
    一、IDFA值会发生改变的情况在何种情况下,应用的IDFA值会发生改变?在iOS的设置应用中选择“重置所有设置”*没有影响在iOS的设置应用中“清除所有的内容和设置”*advertisingIdentifier和identifierForVendor都会受到影响重新设置变为新值通过iTunes还原设备*advertisin......
  • C#开发ESP32E(2)串口配置使用
    1.安装外设配置库(nanoFramework.Hardware.Esp32)和串口使用库(nanoFramework.System.IO)1.1nanoFramework.Hardware.Esp32介绍该库可配置I2C,SPI,Serialports(串口),PWMchannels,ADC、DAC(模数转换和数模转换)配置函数介绍Configuration.SetPinFunction(intpin,DeviceFun......
  • 量产150W 双路输出开关电源全套设计生产资料, 输入220VAC,输出24V5
    量产150W双路输出开关电源全套设计生产资料,输入220VAC,输出24V5A+5V2A,,PCB及原理图使用AD设计,pcb使用元件带3D模型,采用NE1118B作为PWM控制IC,单路24V输出可以过能效6级,电路稳定可靠,可以用着步进电机驱动电源,大功率LED驱动,输出通过调整R9值设置为恒流输出ID:34128616675074391......
  • C#开发ESP32E(1)IO配置操作
    1.Nuget安装nanoFramework.System.Device.Gpio2.创建GpioController和GpioPin对象点击查看代码vargpio=newGpioController();//参数1为引脚号(查看电路图)(此处对应为D2灯)//参数2为模式(输入,输出,上下拉等)(此处对应为输出)varled=gpio.OpenPin(2,PinMode.Output);......