stm32f405rgt6与as5048a的SPI通信问题

与as5048a的SPI通信问题

本人最近在学习无刷直流电机的FOC,其中用了一个带有磁编码器as5048a作为角度反馈的电机,其中pwm接口输出是正常的,但是在SPI通信的时候出现了问题。研究了几天,没搞明白问题出在哪里,希望有大佬可以指点一下小弟。

第一张图是datasheet中截取的,第一位是偶校验,第二位是错误标志。我从as5048a收到的数始终都存在问题。第一次是发送数据地址位,第二次收数为希望的数据,但是得到的是0xC001,连偶校验都不满足,第三次发送的是判断数据有误后发送的清除错误的命令,第四次是发送的一个空指令。

第二张图是逻辑分析仪得到的数据,每100ms发一次,也就是说清除错误标志后还是这样。希望有人可以指点一下。

在这里插入图片描述
在这里插入图片描述
datasheet中还提到,发0x0000,应该收到0x0000,尝试之后没有效果。
在这里插入图片描述在这里插入图片描述

磁编码器程序部分主要是参考的这位:
https://blog.csdn.net/nicholas_dlut/article/details/80937527
foc控制程序参考的这位:
https://www.cnblogs.com/andyfly/p/9915678.html

主函数的循环:

int main(void)
{
	uint8_t tx[2]={0x00,0x00};
	
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2
	SysTick_Init();
	
	LED_Init();//初始化LED端口
			
	EXTI_Key_Config();
	
	USART3_Init(500000);//与上位机通信

	TIM2_Init();//系统计时,用于计算时间
		
	SPI_Config();//采数跳变、存在问题

	TIM5_Init();//用于控制电机三相信号

	TIM6_Init(1000-1,84-1);//1KHz,定时器,用于多任务分频,放在所有外设初始化之后

//	printf("This is a FOC program.\r\r\n");
	while(1)
	{		
		//*******************系统指示灯
		if(gFlag100ms==SET)
		{
			LED1_TOGGLE();
			PitchAngle=Read_As5048A_Reg(0x3FFF);
			gFlag100ms = RESET;
		}
}

SPI配置:

#include "stm32f4xx_conf.h"
#include "spi.h"
#include "delay.h" 

static __IO uint32_t  SPITimeout = SPIT_LONG_TIMEOUT;

void SPI_Config()
{
	SPI_InitTypeDef  spi;
  GPIO_InitTypeDef gpio;
  
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB,ENABLE);
//		RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA|RCC_AHB1Periph_GPIOB|RCC_AHB1Periph_GPIOC|RCC_AHB1Periph_GPIOH,ENABLE);
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2,ENABLE);
	
	//SPI的I/O初始化
	gpio.GPIO_Pin = SPI_SCK_PIN|SPI_MISO_PIN|SPI_MOSI_PIN;
  gpio.GPIO_Speed = GPIO_Low_Speed;
  gpio.GPIO_Mode = GPIO_Mode_AF;
  gpio.GPIO_OType = GPIO_OType_PP;
  gpio.GPIO_PuPd = GPIO_PuPd_UP;
  GPIO_Init(SPI_GPIO_PORT, &gpio);
  
	GPIO_PinAFConfig(SPI_GPIO_PORT,SPI_SCK_PINSOURCE,GPIO_AF_SPI2); 
	GPIO_PinAFConfig(SPI_GPIO_PORT,SPI_MISO_PINSOURCE,GPIO_AF_SPI2); 
	GPIO_PinAFConfig(SPI_GPIO_PORT,SPI_MOSI_PINSOURCE,GPIO_AF_SPI2); 
	
	//片选口
	gpio.GPIO_Pin = ICGCSB_PIN;
  gpio.GPIO_Mode = GPIO_Mode_OUT;
  gpio.GPIO_PuPd = GPIO_PuPd_UP;
  GPIO_Init(ICGCSB_PORT, &gpio);
	GPIO_SetBits(ICGCSB_PORT,ICGCSB_PIN);

	//SPI1初始化
	spi.SPI_Direction = SPI_Direction_2Lines_FullDuplex;//SPI通信方式:2线全双工
  spi.SPI_Mode = SPI_Mode_Master;//SPI主从模式:主机模式
  spi.SPI_DataSize = SPI_DataSize_16b;
  spi.SPI_CPOL = SPI_CPOL_Low;//时钟极性:CPOL=0:串行同步时钟的空闲状态为低电平
  spi.SPI_CPHA = SPI_CPHA_2Edge;//时钟相位:CPHA=1:串行同步时钟的第二个跳变沿(上升或下降)数据被采样
  spi.SPI_NSS = SPI_NSS_Soft;//软件NSS SPI_NSS_Soft  SPI_NSS_Hard
  spi.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_32;//预分频系数 fSCK = 42MHz/SPI_BaudRatePrescaler
  spi.SPI_FirstBit = SPI_FirstBit_MSB;//传输顺序:高位在前
  spi.SPI_CRCPolynomial = 15;//CRC值计算的多项式
  SPI_Init(SPI2, &spi);

  SPI_Cmd(SPI2, ENABLE);//使能SPI
	delay_ms(10);
}


 /**
  * @brief  使用SPI发送2个字节的数据
  * @param  Halfword:要发送的数据
  * @retval 返回接收到的数据
  */

uint16_t SPI_SendHalfWord(uint16_t HalfWord)
{
GPIO_ResetBits(GPIOB, GPIO_Pin_12);

delay_us(1);

SPI_I2S_SendData(SPI2, HalfWord); 


while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET);

GPIO_SetBits(GPIOB, GPIO_Pin_12);

return SPI_I2S_ReceiveData(SPI2);
}

/**
  * @brief  等待超时回调函数
  * @param  None.
  * @retval None.
  */
uint16_t SPI_TIMEOUT_UserCallback(uint8_t errorCode)
{
  /* 等待超时后的处理,输出错误信息 */
  // SPI_ERROR("SPI 等待超时!errorCode = %d",errorCode);
  return 0;
}


收发校验等部分:

// Calculates even parity of 16it value, returns 1 (odd) or 0 (even)
uint8_t parity_even(uint16_t v) 
{
    if(v == 0) return 0;
    v ^= v >> 8;
    v ^= v >> 4;
    v ^= v >> 2;
    v ^= v >> 1;
    return v & 1;
	  //return v ^ 1;
}

uint8_t error_flag;

uint16_t Read_As5048A_Reg(uint16_t cmd)
{
	uint16_t data = 0;
	uint16_t res;
	uint16_t command = 0x4000;// PAR=0 R/W=R
	command = command | cmd;
	command |= ((uint16_t)parity_even(command)<<15);//Add a parity bit on the the MSB
	SPI_SendHalfWord(command);
	delay_us(2);

	res = SPI_SendHalfWord(command);
	delay_us(2);
	error_flag = 0;


	if ((res&0x4000) == 0)//判断第14位是否为0,0为正确值
	{
		data = (res & 0x3FFF);
		error_flag = (parity_even(data) ^ (res >> 15));
		LED2_OFF();
	}
	else//读数据错误,发送清错误命令 
	{
		command = 0x4001;
		SPI_SendHalfWord(command);
		delay_us(2);  
		command = 0x4000;// PAR=0 R/W=R
		command = command | CMD_NOP;
		command |= ((uint16_t)parity_even(command)<<15);//Add a parity bit on the the MSB
		SPI_SendHalfWord(command);
		delay_us(2);
		LED2_ON();
	}
	return data;
}
  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值