找回密码
 立即注册
查看: 1044|回复: 5

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

[复制链接]
  • TA的每日心情
    开心
    昨天 14:47
  • 签到天数: 109 天

    [LV.6]常住居民II

    25

    主题

    304

    回帖

    1025

    积分

    荣誉版主

    Cyber Hamster

    积分
    1025
    发表于 2023-10-19 22:39:37 | 显示全部楼层 |阅读模式
    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位磁编码器 模块长这样:
    O1CN017CJ0Yl2KZ76jMbfEn_!!2876359570.avif.jpg

    O1CN01LnSQX02KZ76dN9fNT_!!2876359570.avif.jpg

    模块原理图:

    原理图.JPG

    串口输出数据:

    截图202310192217481756.jpg


    串口和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[R_Buffer_Len];                //Uart1接收缓存
    unsigned char xdata        T_Buffer[T_Buffer_Len];                //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[RP]=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]);
                            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);
    }
    /*----------------------------分割线----------------------------*/

    完整工程见附件:
    AS5600.zip (1.61 MB, 下载次数: 57)




    (=・ω・=)
    回复 送花

    使用道具 举报

  • TA的每日心情
    开心
    昨天 14:47
  • 签到天数: 109 天

    [LV.6]常住居民II

    25

    主题

    304

    回帖

    1025

    积分

    荣誉版主

    Cyber Hamster

    积分
    1025
     楼主| 发表于 2023-10-20 08:03:14 | 显示全部楼层
    串口输出角度为实时角度,结果在极限值处有10bit回滞,如果配置了开始角度和结束角度,结果为对应的范围,本程序开始角度和结束角度初始化为0,所以结果和角度相等
    (=・ω・=)
    回复 支持 反对 送花

    使用道具 举报

  • TA的每日心情
    开心
    昨天 14:47
  • 签到天数: 109 天

    [LV.6]常住居民II

    25

    主题

    304

    回帖

    1025

    积分

    荣誉版主

    Cyber Hamster

    积分
    1025
     楼主| 发表于 2023-10-20 08:03:15 | 显示全部楼层
    本帖最后由 DebugLab 于 2023-10-20 08:04 编辑

    磁铁使用径向充磁的磁铁
    (=・ω・=)
    回复 支持 反对 送花

    使用道具 举报

  • TA的每日心情
    开心
    2024-1-15 09:24
  • 签到天数: 10 天

    [LV.3]偶尔看看II

    1

    主题

    26

    回帖

    111

    积分

    注册会员

    积分
    111
    发表于 2023-12-20 09:31:43 | 显示全部楼层
    回复 送花

    使用道具 举报

  • TA的每日心情
    无聊
    前天 17:53
  • 签到天数: 118 天

    [LV.6]常住居民II

    3

    主题

    204

    回帖

    562

    积分

    高级会员

    积分
    562
    发表于 2024-1-9 16:38:18 | 显示全部楼层
    这模块板子做的挺好看的,自己打样的?

    点评

    买的成品模块  发表于 2024-1-10 08:06
    回复 支持 反对 送花

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

    GMT+8, 2024-5-3 10:20 , Processed in 0.071125 second(s), 52 queries .

    Powered by Discuz! X3.5

    © 2001-2024 Discuz! Team.

    快速回复 返回顶部 返回列表