【求助】关于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)。
我用软件模拟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) ;
}
社区闲人 发表于 2026-6-20 05:45
我用软件模拟SPI,读MT6825,效果良好。
//SPI先接收高位,形参为接收的bit数,1---8bit
u8 read_angle_8(u8 ...
谢谢回复!我参照你的代码试试!{:baoquan:} 社区闲人 发表于 2026-6-20 05:45
我用软件模拟SPI,读MT6825,效果良好。
//SPI先接收高位,形参为接收的bit数,1---8bit
u8 read_angle_8(u8 ...
用软件SPI才能读取数据,硬件SPI怎么弄都不行!现在还不确定数据是否正确,但起码在没有磁铁时,弱磁标识有效了,把磁铁靠上后,弱磁标识无效,证明读取过程应该是正确的! 项目做的怎么样了,做好了我付费购买,我要用Ai8051U读取两路 MT6816 值,然后通过段数码管显示出来。 gsyfyhvy 发表于 2026-6-27 19:06
项目做的怎么样了,做好了我付费购买,我要用Ai8051U读取两路 MT6816 值,然后通过段数码管显示出来。 ...
软SPI可以读出数据,然后计算度数,能读一路就能读多路,现在用32G串口输出角度,要段码显示需要做一个7段码查表后显示即可。 用软件模拟SPI,更灵活,也便于移植。
页:
[1]