wlhuangcn 发表于 2026-6-19 21:38:42

【求助】关于MT6816读取数据的问题

第一次使用SPI,第一次使用MT6816,配置硬件SPI模式3,用于读取MT6816的角度数据,返回的数据总是0,不知道是什么原因,麻烦有用过的高手指点一下,谢谢!代码如下:
一、GPIO配置


      SPI_Pin_Cfg.Mode = GPIO_OUT_PP; // 定义GPIO的类型为推挽输出
      SPI_Pin_Cfg.Pin = GPIO_Pin_3 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7; // 配置端口I/O引脚
      GPIO_Inilize_Ret= GPIO_Inilize(GPIO_P1, &SPI_Pin_Cfg); // 执行GPIO配置
      SPI_Pin_Cfg.Mode = GPIO_HighZ; // 定义GPIO的类型为推挽输出
      SPI_Pin_Cfg.Pin         = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_4;         // 配置端口I/O引脚
      GPIO_Inilize_Ret= GPIO_Inilize(GPIO_P1, &SPI_Pin_Cfg); // 执行GPIO配置
      
      P1 = 0xFF; // 初始化GPIO状态

二、SPI配置

void SPI_InitialConfig(void)
{
      SPI_InitTypeDef                        SPI_InitStructure; // 定义结构体变量
      SPI_InitStructure.SPI_Enable    = ENABLE;// SPI启动,SPEN=1 使能SPI
      SPI_InitStructure.SPI_SSIG      = ENABLE;    // SSIG=1 忽略硬件NSS:SSIG=1 就是用来禁用硬件 SS 引脚、软件自定义片选
      SPI_InitStructure.SPI_FirstBit= SPI_MSB;   // 数据移位方向 SPI_MSB, SPI_LSB,DORD=0 高位在前
      SPI_InitStructure.SPI_Mode      = SPI_Mode_Master;// 主从选择   SPI_Mode_Master, SPI_Mode_Slave
      SPI_InitStructure.SPI_CPOL      = SPI_CPOL_High; // 时钟相位   SPI_CPOL_High,   SPI_CPOL_Low 模式3
      SPI_InitStructure.SPI_CPHA      = SPI_CPHA_2Edge; // 数据边沿   SPI_CPHA_1Edge,SPI_CPHA_2Edge
      SPI_InitStructure.SPI_Speed   = SPI_Speed_8;// SPI速度    SPI_Speed_4, SPI_Speed_16, SPI_Speed_64, SPI_Speed_128
      SPI_Init(&SPI_InitStructure); // 执行SPI 初始化参数配置
      SPI_SW(SPI_P54_P13_P14_P15);      // SPI引脚映射:MOSI(P1.3)/MISO(P1.4)/SCK(P1.5)
      SPI_MT6816_CSN = 1; // MT6816片选默认拉高/CSN_1(P1.6)
      SPI_ClearFlag();                /* 写 1 清除 SPIF和WCOL 标志 */
}


三、读取MT6816数据代码


u8 MT6816_Read_Reg(u8 RegisterAddr)
{
      u8 ReadCommand = 0x00;      // 定义局部变量
      u8 ReceiveData = 0x00;// 定义局部变量
      
      bit EnableAllINT_Flag;      // 备份原始中断状态
      ReadCommand = RegisterAddr | 0x80;// D7位置位表示为读模式,D6-D0为目标寄存器地址
      EnableAllINT_Flag = EA;// 保存当前总中断状态,避免强行改写
      EA = 0;// 关闭总中断,防止SPI时序出错
      SPI_MT6816_CSN = 0;// 片选低电平,启动MT6816的SPI接口
      NOP6();// 电平稳定延迟,4个NOP,≈166.7ns,满足电平建立时间(24MHz)
      SPI_RW_Byte(ReadCommand);      // 发送读指令和目标寄存器地址,前8位:指令+地址
      ReceiveData = SPI_RW_Byte(0xFF);// 后8位:发哑字节出时钟,同时读数据
      NOP6();// 电平稳定延迟
      SPI_MT6816_CSN = 1;// 片选高电平,关闭MT6816的SPI接口
      NOP6();// 电平稳定延迟
      printf("MT6816寄存器数据:%d \n\r",ReceiveData);// 【测试】
         P1 = 0xFF;// 恢复P1口初始状态【是否需要?】
      EA = EnableAllINT_Flag;// 恢复中断      
      return ReceiveData;
}



u8 SPI_RW_Byte(u8 TxDat)
{
      SPDAT = TxDat;
      while( !(SPSTAT & 0x80) );         // 查询等待传输完成,SPI传输速度快,不需要用中断方式
      SPI_ClearFlag();      // 写 1 清除 SPIF和WCOL 标志
      return SPDAT;   // 返回接收数据
}


四、测试说明
1、从单片机发送0x84命令,再发送0xff以读取MT6816的0x04寄存器的数据,在没有磁铁的情况下,不应返回0,至少应返回0x02;
2、使用USB转SPI转换器,从电脑工具的窗口中可以看到单片机发出的数据是正确的,单片机也能接收到USP转SPI转换器工具软件返回的数据(默认返回0x12)。

社区闲人 发表于 2026-6-20 05:45:36

我用软件模拟SPI,读MT6825,效果良好。
//SPI先接收高位,形参为接收的bit数,1---8bit
u8 read_angle_8(u8 n)
{
        u8 i;
        u8 dat = 0;
       
        for(i = 0; i < n; i ++)
        {
                SPI_MOSI = 0;
                SPI_CLK = 0;                //下降沿
                NOP10();
                dat <<= 1;
               
                SPI_CLK = 1;                //上升沿
                NOP2();
                if(SPI_MISO)
                {
                        dat ++;                //用于8位机
                }
        }
        return dat;
}

//SPI先发送高位,形参为要发送的8位数据
void SPI_SEND_U8_DATA(u8 dat)
{
        u8 i;
       
        for(i = 0; i < 8; i ++)
        {
                if(dat & 0x80)SPI_MOSI = 1;
              else            SPI_MOSI = 0;
                SPI_CLK = 0;                //下降沿
              dat <<= 1;
                NOP10();
                SPI_CLK = 1;                //上升沿
                NOP2();
        }
}



u16 read_6825_angle(void)
{
        u8 l_data;
        u8 h_data;
       
        u8 low_data;
       
        SPI_CS = 0;        //启动SPI
       
        SPI_SEND_U8_DATA(0x83);
       
        h_data = read_angle_8(8);
        l_data = read_angle_8(8);
        low_data = read_angle_8(2);
       
        SPI_CS = 1;
       
        l_data = (l_data & 0xfc) | low_data;
        return (((u16)h_data << 8) | l_data) ;
}

wlhuangcn 发表于 2026-6-20 10:26:49

社区闲人 发表于 2026-6-20 05:45
我用软件模拟SPI,读MT6825,效果良好。
//SPI先接收高位,形参为接收的bit数,1---8bit
u8 read_angle_8(u8 ...

谢谢回复!我参照你的代码试试!{:baoquan:}

wlhuangcn 发表于 2026-6-20 21:37:10

社区闲人 发表于 2026-6-20 05:45
我用软件模拟SPI,读MT6825,效果良好。
//SPI先接收高位,形参为接收的bit数,1---8bit
u8 read_angle_8(u8 ...

用软件SPI才能读取数据,硬件SPI怎么弄都不行!现在还不确定数据是否正确,但起码在没有磁铁时,弱磁标识有效了,把磁铁靠上后,弱磁标识无效,证明读取过程应该是正确的!

gsyfyhvy 发表于 2026-6-27 19:06:37

项目做的怎么样了,做好了我付费购买,我要用Ai8051U读取两路 MT6816 值,然后通过段数码管显示出来。

wlhuangcn 发表于 2026-6-29 20:09:30

gsyfyhvy 发表于 2026-6-27 19:06
项目做的怎么样了,做好了我付费购买,我要用Ai8051U读取两路 MT6816 值,然后通过段数码管显示出来。 ...

软SPI可以读出数据,然后计算度数,能读一路就能读多路,现在用32G串口输出角度,要段码显示需要做一个7段码查表后显示即可。

社区闲人 发表于 2026-6-30 08:12:37

用软件模拟SPI,更灵活,也便于移植。
页: [1]
查看完整版本: 【求助】关于MT6816读取数据的问题