DebugLab 发表于 2023-10-19 22:39:37

51 开源 I2C-磁编码器-AS5600,12位磁编码器,通过串口发送

51 开源 I2C-磁编码器-AS5600,12位磁编码器,通过串口发送本程序实现AS5600读取各参数从串口发送的功能,注意AS5600有OTP存储器,通过IO口编程(GPO=0才能通过IO口编程,建议去掉R4避免误操作)只能执行1次,通过IO口或I2C编程只能执行3次,此操作不可逆,建议去掉R1使用5V模式,不去掉R1只能使用3.3V模式,5V模式最大增益255,3.3V模式最大增益128。
单片机 STC8G1K08A-8PIN,时钟频率11.0592MHz,UART1,115200bps,8N1,AS5600-12位磁编码器,使用成品模块。
AS5600-12位磁编码器 模块长这样:


模块原理图:


串口输出数据:


串口和printf的使用见此连接:
https://www.stcaimcu.com/forum.php?mod=viewthread&tid=4598
附带部分中文数据手册,重要部分已翻译。

/*----------------------------分割线----------------------------*/

#include <STC8G.H>
#include "define.h"
#include <intrins.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#define                RXD                P30
#define                TXD                P31
#define                SCL                P32
#define                SDA                P33
#define                FOSC                11059200UL
#define                BAUD                115200UL
#define                BRT                        (0x10000-FOSC/BAUD/4)
#define                T_Buffer_Len      64      //Uart1发送缓存长度
#define                R_Buffer_Len      64      //Uart1接收缓存长度
#define                AS5600_Write      0x6C
#define                AS5600_Read                0x6D


unsigned char                RP;                                                      //Uart1接收指针
unsigned char                TP;                                                      //Uart1发送指针
unsigned char                Uart_Send_Lenth;                        //Uart1发送长度
unsigned char xdata      R_Buffer;                //Uart1接收缓存
unsigned char xdata      T_Buffer;                //Uart1发送缓存
bit I2C_Busy;


/*----------------------------延时10us@STC-Y6@11.0592MHz----------------------------*/
void Delay_10us(void)
{
      unsigned char i;
      i=35;
      while(--i);
}


/*----------------------------延时x10us----------------------------*/
void Delay_x10us(unsigned char x)
{
      while(x--)
                Delay_10us();
}


/*----------------------------延时10ms@STC-Y6@11.0592MHz----------------------------*/
void Delay_10ms(void)
{
      unsigned char i,j;
      _nop_();
      _nop_();
      i=144;
      j=157;
      do
      {
                while(--j);
      }while(--i);
}


/*----------------------------延时x10ms----------------------------*/
void Delay_x10ms(unsigned char x)
{
      while(x--)
                Delay_10ms();
}


void UART_Send(unsigned int x)
{
      TP=0;
      Uart_Send_Lenth=x;
      TI=1;
}


void Uart_Printf(unsigned char *v,...)
{
      va_list ap;
      va_start(ap,v);
      while(Uart_Send_Lenth);
      UART_Send(vsprintf(T_Buffer,v,ap));
      va_end(ap);
}


void I2C_Start(void)
{
      I2C_Busy=1;
      I2CMSCR=0x81;
      while(I2C_Busy);
}


void I2C_SendData(unsigned char dat)
{
      I2CTXD=dat;
      I2C_Busy=1;
      I2CMSCR=0x82;
      while(I2C_Busy);
}


void I2C_RecvACK(void)
{
      I2C_Busy=1;
      I2CMSCR=0x83;
      while(I2C_Busy);
}


unsigned char I2C_RecvData(void)
{
      I2C_Busy=1;
      I2CMSCR=0x84;
      while(I2C_Busy);
      return I2CRXD;
}


void I2C_SendACK(void)
{
      I2CMSST=0x00;
      I2C_Busy=1;
      I2CMSCR=0x85;
      while(I2C_Busy);
}


void I2C_SendNAK(void)
{
      I2CMSST=0x01;
      I2C_Busy=1;
      I2CMSCR=0x85;
      while(I2C_Busy);
}


void I2C_Stop(void)
{
      I2C_Busy=1;
      I2CMSCR=0x86;
      while(I2C_Busy);
}


void AS5600_Write_One_Byte(unsigned char addr,unsigned char dat)
{
      I2C_Start();
      I2C_SendData(AS5600_Write);
      I2C_RecvACK();
      I2C_SendData(addr);
      I2C_RecvACK();
      I2C_SendData(dat);
      I2C_RecvACK();
      I2C_Stop();
}


void AS5600_Write_Two_Byte(unsigned char addr,unsigned int dat)
{
      I2C_Start();
      I2C_SendData(AS5600_Write);
      I2C_RecvACK();
      I2C_SendData(addr);
      I2C_RecvACK();
      I2C_SendData((unsigned char)(dat>>8));
      I2C_RecvACK();
      I2C_SendData((unsigned char)(dat&0x00FF));
      I2C_RecvACK();
      I2C_Stop();
}


unsigned char AS5600_Read_One_Byte(unsigned char addr)
{
      unsigned char dat;
      I2C_Start();
      I2C_SendData(AS5600_Write);
      I2C_RecvACK();
      I2C_SendData(addr);
      I2C_RecvACK();
      I2C_Start();
      I2C_SendData(AS5600_Read);
      I2C_RecvACK();
      dat=I2C_RecvData();
      I2C_SendNAK();
      I2C_Stop();
      return dat;
}


unsigned int AS5600_Read_Two_Byte(unsigned char addr)
{
      unsigned char msb,lsb;
      unsigned int dat;
      I2C_Start();
      I2C_SendData(AS5600_Write);
      I2C_RecvACK();
      I2C_SendData(addr);
      I2C_RecvACK();
      I2C_Start();
      I2C_SendData(AS5600_Read);
      I2C_RecvACK();
      msb=I2C_RecvData();
      I2C_SendACK();
      lsb=I2C_RecvData();
      I2C_SendNAK();
      I2C_Stop();
      dat=(unsigned int)msb<<8;
      dat|=(unsigned int)lsb;
      return dat;
}


void AS5600_Init(void)
{
      AS5600_Write_Two_Byte(0x01,0x00);
      Delay_x10us(100);
      AS5600_Write_Two_Byte(0x03,0x00);
      Delay_x10us(100);
      AS5600_Write_One_Byte(0x07,0x00);
      Delay_x10us(100);
      AS5600_Write_One_Byte(0x08,0x00);
      Delay_x10us(100);
//      AS5600_Write_One_Byte(0xFF,0x80);      //警告:此操作不可逆!
//      Delay_x10us(100);
      Uart_Printf("ZMCO=%BU\r\n",AS5600_Read_One_Byte(0x00));
      Uart_Printf("ZPOS=%U\r\n",AS5600_Read_Two_Byte(0x01));
      Uart_Printf("MPOS=%U\r\n",AS5600_Read_Two_Byte(0x03));
      Uart_Printf("MANG=%U\r\n",AS5600_Read_Two_Byte(0x05));
      Uart_Printf("CONF=0x%02BX%02BX\r\n",AS5600_Read_One_Byte(0x07),AS5600_Read_One_Byte(0x08));
}


void Init(void)
{
      P_SW2|=EAXFR;
      
      P3M0=0x00;
      P3M1=0x00;
      P5M0=0x00;
      P5M1=0x00;
      P3PU=0x0c;
      
      AUXR=0x40;                //设置定时器0时钟为12T模式,设置定时器1为1T模式,设置定时器1为波特率发生器
      TMOD=0x01;                //设置定时器0为16位不自动重装载模式,设置定时器1为16位自动重装载模式
      TL0=0x00;                //设置定时器0初始值(5ms)
      TH0=0xEE;                //设置定时器0初始值(5ms)
      TF0=0;                        //清除TF0中断标志位
      ET0=1;                        //启用定时器0中断
      
      SCON=0x50;                //设置UART1模式为8位数据可变波特率
      TL1=BRT;                //设置UART1波特率
    TH1=BRT>>8;                //设置UART1波特率
      TR1=1;                        //打开定时器1
      ES=1;                        //启用UART1中断
      
      I2CCFG=0xC6;      //345.6K@11.0592M
      I2CMSCR=EMSI;
      I2CMSST=0x00;
      
      EA=1;                        //启用总中断
      
      AS5600_Init();
}


void main(void)
{
      Init();
      while(1)
      {
                Uart_Printf("角度=%04U 结果=%04U 检测到磁铁=%BU 磁场太弱=%BU 磁场太强=%BU 增益=%03BU 幅度=%04U\r\n",AS5600_Read_Two_Byte(0x0C),AS5600_Read_Two_Byte(0x0E),(AS5600_Read_One_Byte(0x0B)&0x20)>>5,(AS5600_Read_One_Byte(0x0B)&0x10)>>4,(AS5600_Read_One_Byte(0x0B)&0x08)>>3,AS5600_Read_One_Byte(0x1A),AS5600_Read_Two_Byte(0x1B));
                Delay_x10ms(2);
      }
}


void Uart_Start(void)
{
      TL0=0x00;
      TH0=0xEE;
      TR0=1;
}


void Uart_Stop(void)
{
      TR0=0;
      TL0=0x00;
      TH0=0xEE;
      RP=0;
      memset(R_Buffer,0x00,sizeof R_Buffer);
}


void Timer0_Isr(void) interrupt 1
{
      Uart_Stop();
}


void Uart_Isr(void) interrupt 4
{
      if(RI)
      {
                RI=0;
                Uart_Start();
                R_Buffer=SBUF;
                if(RP==0)
                {
                        IAP_CONTR=0x60;
                }
                if(RP==R_Buffer_Len-1)
                {
                        Uart_Stop();
                }
                else if(TR0)
                {
                        RP++;
                }
      }
      if(TI)
      {
                TI=0;
                if(Uart_Send_Lenth!=0)
                {
                        SBUF=(T_Buffer);
                        TP++;
                }
                if(TP==Uart_Send_Lenth)
                {
                        TP=0;
                        Uart_Send_Lenth=0;
                }
      }
}


void I2C_Isr(void) interrupt 24
{
      _push_(P_SW2);
      P_SW2|=EAXFR;
      if(I2CMSST&MSIF)
      {
                I2CMSST&=~MSIF;
                I2C_Busy=0;
      }
      _pop_(P_SW2);
}
/*----------------------------分割线----------------------------*/

完整工程见附件:





DebugLab 发表于 2023-10-20 08:03:14

串口输出角度为实时角度,结果在极限值处有10bit回滞,如果配置了开始角度和结束角度,结果为对应的范围,本程序开始角度和结束角度初始化为0,所以结果和角度相等

DebugLab 发表于 2023-10-20 08:03:15

本帖最后由 DebugLab 于 2023-10-20 08:04 编辑

磁铁使用径向充磁的磁铁

twfx 发表于 2023-12-20 09:31:43

{:4_250:}

Snapdragon 发表于 2024-1-9 16:38:18

这模块板子做的挺好看的{:4_250:},自己打样的?

ofela 发表于 2024-8-7 08:37:23

求助,AS5600磁编码器怎么模拟出多圈角度呢

DebugLab 发表于 2024-8-7 09:26:23

ofela 发表于 2024-8-7 08:37
求助,AS5600磁编码器怎么模拟出多圈角度呢

不支持的

men007 发表于 2024-12-12 10:00:42

学习了

jackduan 发表于 2025-2-20 17:18:27

感谢大神分享{:baoquan:}
页: [1]
查看完整版本: 51 开源 I2C-磁编码器-AS5600,12位磁编码器,通过串口发送