芯片F103CBT6,使用cubeide+hal库,驱动部分源码移植于:

(22条消息) STM32使用模拟I2C读取AS5600(深入讲解:带波形图)_yizeni的博客-CSDN博客_as5600使用方法

对函数以及全局变量进行了适当的封装与static声明,能计算上电后相对初始位置的转角与圈数,utf8跟gbk互转的时候部分搞出乱码了,将就看看。

AS5600.h:

/** as5600.h**  Created on: Jan 19, 2023*      Author: Administrator*/#ifndef _AS5600_H
#define _AS5600_H#include "sys.h"
#include "main.h"//角度相关的全项目全局变量
extern short relativeAngle;//相对旋转角度
extern short totalAngle;//总旋转角度
extern short numberofTurns;//旋转圈数//IO方向设置,这个是位带操作法
//#define SDA_IN()  {GPIOB->CRL&=0X0FFFFFFF;GPIOB->CRL|=(u32)8<<28;} //SDA切换为输入模式
//#define SDA_OUT() {GPIOB->CRL&=0X0FFFFFFF;GPIOB->CRL|=(u32)3<<28;} //SDA切换为输出模式//IO操作函数
#define IIC_SCL    PBout(3) //SCL输出
#define IIC_SDA    PBout(4) //SDA输出
#define READ_SDA   PBin(4)  //SDA输入//AS5600的高低地址
#define _raw_ang_hi 0x0c
#define _raw_ang_lo 0x0d/*AS5600驱动的静态函数封装
static u8 AS5600_ReadOneByte(u16 ReadAddr);
static void AS5600_WriteOneByte(u16 WriteAddr,u8 WriteData);
static u16 AS5600_ReadTwoByte(u16 ReadAddr_hi,u16 ReadAddr_lo);
*/void AS5600_Test(void);//测试,每次依次输出寄存器读值,绝对角度值,相对角度值,圈数void RelativeAngleCorrect(short startAngle, short realAngle);//相对角度正值化
void checkQuadrant(void);//用象限来计算圈数,顺时针转为正#endif

AS5600.c

/** as5600.c**  Created on: Jan 19, 2023*      Author: Administrator*/#include "as5600.h"
#include "Delay.h"
#include "stm32f1xx_hal.h"
#include <stdio.h>/*  iic底层相关静态函数*///IO方向设置
static void SDA_IN(void);
static void SDA_OUT(void);//iic驱动
static void IIC_Init(void);                //³õʼ»¯IICµÄIO¿Ú
static void IIC_Start(void);                //·¢ËÍIIC¿ªÊ¼ÐźÅ
static void IIC_Stop(void);             //·¢ËÍIICÍ£Ö¹ÐźÅ
static void IIC_Send_Byte(u8 txd);          //IIC·¢ËÍÒ»¸ö×Ö½Ú
static u8 IIC_Read_Byte(unsigned char ack);//IIC¶ÁÈ¡Ò»¸ö×Ö½Ú
static u8 IIC_Wait_Ack(void);               //IICµÈ´ýACKÐźÅ
static void IIC_Ack(void);                  //IIC·¢ËÍACKÐźÅ
static void IIC_NAck(void);             //IIC²»·¢ËÍACKÐźÅ//as5600驱动
static u8 AS5600_ReadOneByte(u16 ReadAddr);
static void AS5600_WriteOneByte(u16 WriteAddr,u8 WriteData);
static u16 AS5600_ReadTwoByte(u16 ReadAddr_hi,u16 ReadAddr_lo);//static void IIC_Write_One_Byte(u8 daddr,u8 addr,u8 data);
//static u8 IIC_Read_One_Byte(u8 daddr,u8 addr);//角度相关全局变量
short relativeAngle = 0;//相对旋转角度
short totalAngle = 0;//总旋转角度
short numberofTurns = 0;//旋转圈数static short previousquadrantNumber = 0;//上次象限
static short quadrantNumber = 0;//当前象限static void SDA_IN(void){GPIO_InitTypeDef GPIO_InitStruct = {0};GPIO_InitStruct.Pin = SDA_Pin;GPIO_InitStruct.Mode = GPIO_MODE_INPUT;GPIO_InitStruct.Pull = GPIO_NOPULL;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;HAL_GPIO_Init(SDA_GPIO_Port, &GPIO_InitStruct);
}static void SDA_OUT(void){GPIO_InitTypeDef GPIO_InitStruct = {0};GPIO_InitStruct.Pin = SDA_Pin;GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD;GPIO_InitStruct.Pull = GPIO_NOPULL;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;HAL_GPIO_Init(SDA_GPIO_Port, &GPIO_InitStruct);
}//³õʼ»¯IIC
static void IIC_Init(void)
{GPIO_InitTypeDef GPIO_InitStruct = {0};/* GPIO Ports Clock Enable */__HAL_RCC_GPIOD_CLK_ENABLE();__HAL_RCC_GPIOB_CLK_ENABLE();__HAL_RCC_GPIOA_CLK_ENABLE();/*Configure GPIO pin : SCL_Pin */GPIO_InitStruct.Pin = SCL_Pin;GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;GPIO_InitStruct.Pull = GPIO_NOPULL;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;HAL_GPIO_Init(SCL_GPIO_Port, &GPIO_InitStruct);/*Configure GPIO pin : SDA_Pin */GPIO_InitStruct.Pin = SDA_Pin;GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD;GPIO_InitStruct.Pull = GPIO_NOPULL;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;HAL_GPIO_Init(SDA_GPIO_Port, &GPIO_InitStruct);
}
//²úÉúIICÆðʼÐźÅ
static void IIC_Start(void)
{SDA_OUT();     //sdaÏßÊä³öIIC_SDA=1;IIC_SCL=1;Delay_us(4);IIC_SDA=0;//START:when CLK is high,DATA change form high to lowDelay_us(4);IIC_SCL=0;//ǯסI2C×ÜÏߣ¬×¼±¸·¢ËÍ»ò½ÓÊÕÊý¾Ý
}
//²úÉúIICÍ£Ö¹ÐźÅ
static void IIC_Stop(void)
{SDA_OUT();//sdaÏßÊä³öIIC_SCL=0;IIC_SDA=0;//STOP:when CLK is high DATA change form low to highDelay_us(4);IIC_SCL=1;IIC_SDA=1;//·¢ËÍI2C×ÜÏß½áÊøÐźÅDelay_us(4);
}
//µÈ´ýÓ¦´ðÐźŵ½À´
//·µ»ØÖµ£º1£¬½ÓÊÕÓ¦´ðʧ°Ü
//        0£¬½ÓÊÕÓ¦´ð³É¹¦
static u8 IIC_Wait_Ack(void)
{u8 ucErrTime=0;SDA_IN();      //SDAÉèÖÃΪÊäÈëIIC_SDA=1;Delay_us(1);IIC_SCL=1;Delay_us(1);while(READ_SDA){ucErrTime++;if(ucErrTime>250){IIC_Stop();return 1;}}IIC_SCL=0;//ʱÖÓÊä³ö0return 0;
}
//²úÉúACKÓ¦´ð
static void IIC_Ack(void)
{IIC_SCL=0;SDA_OUT();IIC_SDA=0;Delay_us(2);IIC_SCL=1;Delay_us(2);IIC_SCL=0;
}
//²»²úÉúACKÓ¦´ð
static void IIC_NAck(void)
{IIC_SCL=0;SDA_OUT();IIC_SDA=1;Delay_us(2);IIC_SCL=1;Delay_us(2);IIC_SCL=0;
}
//IIC·¢ËÍÒ»¸ö×Ö½Ú
//·µ»Ø´Ó»úÓÐÎÞÓ¦´ð
//1£¬ÓÐÓ¦´ð
//0£¬ÎÞÓ¦´ð
static void IIC_Send_Byte(u8 txd)
{u8 t;SDA_OUT();IIC_SCL=0;//À­µÍʱÖÓ¿ªÊ¼Êý¾Ý´«Êäfor(t=0;t<8;t++){//IIC_SDA=(txd&0x80)>>7;if((txd&0x80)>>7)IIC_SDA=1;elseIIC_SDA=0;txd<<=1;Delay_us(2);   //¶ÔTEA5767ÕâÈý¸öÑÓʱ¶¼ÊDZØÐëµÄIIC_SCL=1;Delay_us(2);IIC_SCL=0;Delay_us(2);}
}//¶Á1¸ö×Ö½Ú£¬ack=1ʱ£¬·¢ËÍACK£¬ack=0£¬·¢ËÍnACK
static u8 IIC_Read_Byte(unsigned char ack)
{unsigned char i,receive=0;SDA_IN();//SDAÉèÖÃΪÊäÈëfor(i=0;i<8;i++ ){IIC_SCL=0;Delay_us(2);IIC_SCL=1;receive<<=1;if(READ_SDA)receive++;Delay_us(1);}if (!ack)IIC_NAck();//·¢ËÍnACKelseIIC_Ack(); //·¢ËÍACKreturn receive;
}//ÔÚAS5600Ö¸¶¨µØÖ·¶Á³öÒ»¸öÊý¾Ý
static u8 AS5600_ReadOneByte(u16 ReadAddr)
{u8 temp=-1;IIC_Start();IIC_Send_Byte((0X36<<1)|0x00);      //·¢ËÍдÃüÁîIIC_Wait_Ack();IIC_Send_Byte(ReadAddr);   //·¢Ë͵ØÖ·IIC_Wait_Ack();IIC_Start();IIC_Send_Byte((0X36<<1)|0x01);           //½øÈë½ÓÊÕģʽIIC_Wait_Ack();temp=IIC_Read_Byte(0);IIC_Stop();//²úÉúÒ»¸öÍ£Ö¹Ìõ¼þreturn temp;
}//ÔÚAS5600Ö¸¶¨µØÖ··¢ËͳöÒ»¸öÊý¾Ý
static void AS5600_WriteOneByte(u16 WriteAddr,u8 WriteData)
{IIC_Start();IIC_Send_Byte((0X36<<1)|0x00);      //·¢ËÍдÃüÁîIIC_Wait_Ack();IIC_Send_Byte(WriteAddr);     //·¢Ë͵ØÖ·IIC_Wait_Ack();IIC_Start();IIC_Send_Byte(WriteData);          //·¢ËÍÊý¾ÝIIC_Wait_Ack();IIC_Stop();//²úÉúÒ»¸öÍ£Ö¹Ìõ¼þHAL_Delay(10);
}//¶ÁÈ¡Á½Î»Êý¾Ý
static u16 AS5600_ReadTwoByte(u16 ReadAddr_hi,u16 ReadAddr_lo)
{u16 TwoByte_Data=-1;u8 hi_Data=0,lo_Data=0;hi_Data=AS5600_ReadOneByte(ReadAddr_hi);lo_Data=AS5600_ReadOneByte(ReadAddr_lo);TwoByte_Data = (hi_Data<<8)|lo_Data;return TwoByte_Data;
}void AS5600_Test(void){//配置顺时针为正IIC_Init();short raw_num = 0;//寄存器读值short real_start_angle = 0;//初始绝对角度short real_angle = 0;//读取的绝对角度//获取初始角raw_num = AS5600_ReadTwoByte(_raw_ang_hi,_raw_ang_lo);real_start_angle = (raw_num*360)/4096; //对寄存器值进行处理得到角度值while (1){raw_num = AS5600_ReadTwoByte(_raw_ang_hi,_raw_ang_lo);  //读取两个寄存器的值//printf("adr num: %d\r\n",raw_num);real_angle = (raw_num*360)/4096; //对寄存器值进行处理得到角度值RelativeAngleCorrect(real_start_angle, real_angle);//获得相对角度checkQuadrant();printf("\r\n");printf("寄存器读值: %d\r\n",raw_num);printf("绝对角度: %d\r\n",real_angle);printf("相对角度: %d\r\n",relativeAngle);printf("圈数: %d\r\n",numberofTurns);printf("\r\n");LED_TURN;HAL_Delay(100);}
}void RelativeAngleCorrect(short startAngle, short realAngle){//相对角度获取,顺时针为正relativeAngle = realAngle - startAngle; //没变动则为0if(relativeAngle < 0) //把相对角度转换为0-360度表示{relativeAngle = relativeAngle + 360; //}//把0-360角度转换为-180到+180表示if(relativeAngle > 180){relativeAngle = relativeAngle - 360;}
}void checkQuadrant(void)
{//用象限来计算圈数,顺时针转为正/*//Quadrants:4  |  1---|---3  |  2*///Quadrant 1if(relativeAngle > 0 && relativeAngle <=90){quadrantNumber = 1;}//Quadrant 2if(relativeAngle > 90 && relativeAngle <=180){quadrantNumber = 2;}//Quadrant 3if(relativeAngle > -180 && relativeAngle <=-90){quadrantNumber = 3;}//Quadrant 4if(relativeAngle > -90 && relativeAngle <0){quadrantNumber = 4;}if(quadrantNumber != previousquadrantNumber) //如果象限改变{if(quadrantNumber == 1 && previousquadrantNumber == 4){numberofTurns++; // 现在象限为1而上次为4,则顺时针旋转过0一次,圈数加1}if(quadrantNumber == 4 && previousquadrantNumber == 1){numberofTurns--; // 现在象限为4而上次为1,则逆时针旋转过0一次,圈数减1}previousquadrantNumber = quadrantNumber;  //更新旧象限}totalAngle = (numberofTurns*360) + relativeAngle; //number of turns (+/-) plus the actual angle within the 0-360 range}

附件:一个hal库的systick延时库

/** Delay.c**  Created on: Jan 19, 2023*      Author: Administrator*//* --------------------------------------------------------- */
// 文件名称:delay.c
// 功能描述: SysTick延时函数源文件/* --------------------------------------------------------- */#include "Delay.h"
#include "main.h"
#include "stm32f1xx_hal.h"float usDelayBase;
void PY_usDelayTest(void)
{uint32_t firstms, secondms;uint32_t counter = 0;firstms = HAL_GetTick()+1;secondms = firstms+1;while(uwTick!=firstms) ;while(uwTick!=secondms) counter++;usDelayBase = ((float)counter)/1000;
}void Delay_us_t(uint32_t Delay)
{uint32_t delayReg;uint32_t usNum = (uint32_t)(Delay*usDelayBase);delayReg = 0;while(delayReg!=usNum) delayReg++;
}void PY_usDelayOptimize(void)
{uint32_t firstms, secondms;float coe = 1.0;firstms = HAL_GetTick();Delay_us_t(1000000) ;secondms = HAL_GetTick();coe = ((float)1000)/(secondms-firstms);usDelayBase = coe*usDelayBase;
}void Delay_us(uint32_t Delay)
{uint32_t delayReg;uint32_t msNum = Delay/1000;uint32_t usNum = (uint32_t)((Delay%1000)*usDelayBase);if(msNum>0) HAL_Delay(msNum);delayReg = 0;while(delayReg!=usNum) delayReg++;
}

IIC读取AS5600磁编码器并计算相对角度与圈数代码移植相关推荐

  1. stm32 hal库 AS5600磁编码器IIC通信读取角度

    stm32 hal库 AS5600磁编码器IIC通信读取角度 下载

  2. AS5600 磁编码器的使用教程,“划时代”的设计真的好用吗?

    前言 如果说我们要判断一个旋钮的位置,或者是判断一个电机转了多少圈,这个电机当前的角度是什么,那么我们就会需要使用到编码器. 传统的光栅方式的编码器多是增量式,输出数字编码数值,它有两个输出 连接的处 ...

  3. AS5600 磁编码器的调试经验

    AS5600 磁编码器的调试经验 1. 硬件 2. GPIO功能清单 3.软件寄存器 4.软件代码 1. 硬件 购买了淘宝上的磁编码器如图所示 原理图大概如图 2. GPIO功能清单 只对使用到的GP ...

  4. AS5600磁编码器的使用以及简单的滤波算法(arduino)

    目录 前言 实践 示例一:发现IIC设备 示例二:读取AS5600原始数据 示例三:对读取到的AS5600原始数据进行低通滤波 1. 一阶滤波算法的原理 2.编程实现 前言 AS5600磁编码器常用于 ...

  5. AS5600 磁编码器使用心得及总结

    AS5600 磁编码器使用心得及总结 最近复现自平衡莱洛三角 使用到了AS5600这个传感器,记录一些有用的点,方便后续再次的使用 一.编码器 1.编码器 无论是旋转编码器还是线性编码器,绝对编码器或 ...

  6. AS5600磁编码器开发记录

    AS5600使用简介--(程序员版) -----------------本文由"智御电子"提供,同时提供范例教程,以便电子爱好者交流学习.---------------- 前言: ...

  7. AS5600磁编码器原理图和驱动

    一. 简介 原理图如下.12位分辨率,输出为0-4096.对应为0-360°. 采用IIC进行通信,器件地址为0x6C. 寄存器如下,要获取角度数据,只需要读取0x0F和0x0E两个寄存器即可,不需要 ...

  8. 【FOC控制】英飞凌TC264无刷驱动方案simplefoc移植(5)-磁编码器移植AS5600 软件IIC

    [FOC控制]英飞凌TC264无刷驱动方案simplefoc移植(5)-磁编码器移植 [FOC控制]英飞凌TC264无刷驱动方案simplefoc移植(5)-磁编码器移植 一.编码器选择 二.通讯方式 ...

  9. 位置检测有哪些传感器可以用?(带磁编码器AS5600代码)

    常见的有三种 编码器.霍尔传感器.磁传感器. 编码器一般指AB相正交脉冲的增量器件,有的还会有一个Z相信号,用来指示零位: 霍尔传感器一般是指ABC三个成120度角度间隔排列的器件,这种传感器一般集成 ...

最新文章

  1. Python的基本运算符
  2. python简单代码演示效果-10分钟教你用python 30行代码搞定简单手写识别!
  3. 全面改用HTML5+CSS3来架构
  4. docker设置http_proxy https_proxy解决gcr.io/kaniko-project/executor:v1.7.0之类的镜像拉取问题
  5. 模电知识,大师 书本
  6. 如何查看自己的Github仓库占据了多少存储空间
  7. String.valueOf(Object)与Objects.toString(Object)
  8. windows os x linux比较,对比测试:Ubuntu 11.04 vs Win7 vs OS X 10.7
  9. 基于角色的访问控制模型(RBAC)——学习笔记
  10. Kali Linux 网络扫描秘籍 第二章 探索扫描(二)
  11. Linux Ctrl+c与ctrl+z的区别
  12. 为什么我的数据库应用程序这么慢?
  13. Win7-64位 Cygwin编译Redis
  14. 软件测试常用的黑盒测试方法有哪些,简述什么是黑盒测试方法(最常用的黑盒测试方法)...
  15. 第2次作业:微博软件分析
  16. AI人工智能(调包侠)速成之路十四(中国象棋AI网络机器人:AI技术综合应用实现)
  17. python自动注册邮箱_python自动化办公——邮箱
  18. python编程心得体会800字_学习python的心得体会
  19. Windows 安装 Docker
  20. 顶级域名、一级域名、二级域名、子域名如何区分

热门文章

  1. VCIP 2020:面向VVC的自适应分辨率改变
  2. jmeter教程:性能测试执行及结果分析
  3. iconfont怎么引入html,Web页面中引用iconfont图标
  4. 华为S2700以及S5700系列交换机 配置(详细)
  5. 8051单片机基础2:内核和存储器(RAM,Flash)架构
  6. Fun之使用火绒剑对AsmToE工具行为分析
  7. 官方2013年6月CISA考试报名时间公布
  8. 南昌大学 计算机面试题,南昌大学计算机应用技术专业调剂生复试经验
  9. 蔡学镛在支付宝工作那段时间,最让不开心的事情揭秘
  10. 相应的游戏服务器组件信息不存在,房间创建失败