项目进展(四)-双电机均可驱动,配置模拟SPI,调平仪功能初步实现!

一、前言

  截止到今天,该项目也算实现基本功能了,后续继续更新有关32位ADC芯片相关的内容,今天对驱动芯片做一个总结,也对模拟SPI做一点总结吧

二、模拟SPI

  由于模拟SPI还是得有四种模式(CPOL和CPHA组合为四种),下面是我参考的模拟SPI的链接:SPI介绍+软件模拟SPI,本文介绍的相当详细,也有源代码,我们的项目就是采用该博主的第二种模式,只不过根据MCT8316ZR芯片做了部分修改,以适应驱动芯片。

模式0:CPOL=0,CPHA =0 SCK空闲为低电平,数据在SCK的上升沿被采样(提取数据)
模式1:CPOL=0,CPHA =1 SCK空闲为低电平,数据在SCK的下降沿被采样(提取数据)
模式2:CPOL=1,CPHA =0 SCK空闲为高电平,数据在SCK的下降沿被采样(提取数据)
模式3:CPOL=1,CPHA =1 SCK空闲为高电平,数据在SCK的上升沿被采样(提取数据)

三、模拟SPI驱动电机

  基本的寄存器配置和第一个电机的配置一样,只不过在ILIM引脚上并联的电阻大小不一样,这个电机在电阻上并联了200KΩ电阻,电机转的很快,也比较丝滑(由于机械原因可能稍微有点刺耳的声音),但是前面驱动的第一个电机需要并联330KΩ才可以,并联200K的反而无法运转,只是有响声。
  所以若是您也在配置该电机,建议详细阅读数据手册,尤其是相关ILIM引脚的说明:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

四、展示视频

调平仪

五、MCT8316ZR源码

  MCT8316ZR.c

#include "MCT8316.h"
#include "spi.h"
#include "math.h"


uint16_t tx, rx=10;
static uint8_t tx_buff[14];

uint8_t status[10] = {100,100,100,100,100,100,100,100,100,100};
uint8_t addr,dat;


uint8_t MCT8316_read_buffer(uint8_t const regAddr, uint8_t *pData, uint8_t len)
{
  HAL_GPIO_WritePin(GPIOA, motor_1_CS_Pin,0);
  tx = regAddr | 0x80;
  tx_buff[0] = tx;
  HAL_SPI_TransmitReceive(&hspi1, (uint8_t *)&tx, (uint8_t *)&rx, 1, 55);
  HAL_SPI_TransmitReceive(&hspi1, tx_buff, pData, len, 55);
  HAL_GPIO_WritePin(GPIOA, motor_1_CS_Pin,1);
  return 0;
}
 
 
uint8_t MCT8316_write_reg(uint8_t reg,uint8_t val)
{
 
	HAL_GPIO_WritePin(GPIOA, motor_1_CS_Pin,0);// CS引脚拉低
	tx = reg & 0x7F; 
	
	tx = (tx<<8)|val;
  HAL_SPI_TransmitReceive(&hspi1, (uint8_t *)&tx, (uint8_t *)&rx, 1, 55);
//  tx = val;
//  HAL_SPI_TransmitReceive(&hspi1, &tx, &rx, 1, 55);
	// HAL_Delay(10);
	HAL_GPIO_WritePin(GPIOA, motor_1_CS_Pin,1);
 
	return 0;
}
 
 
uint8_t MCT8316_read_reg(uint8_t reg)
{
	HAL_GPIO_WritePin(GPIOA, motor_1_CS_Pin,0);
	tx = (reg<<1) & 0x7E;
	tx = (0x80|tx|ParityCheck(tx));  // 异或
	tx = (tx<<8)|0xFF;
	HAL_SPI_TransmitReceive(&hspi1,(uint8_t *) &tx, (uint8_t *)&rx, 1, 55);
//	tx = 0XFF;
//  HAL_SPI_TransmitReceive(&hspi1, &tx, &rx, 1, 55);//这个应该是随便发一个数就行
	HAL_GPIO_WritePin(GPIOA, motor_1_CS_Pin,1);//源代码发送的是ff
	
	return rx&0xFF;
}

void MCT8316_Init(void)
{
	
	
	addr = (Control_Register_1<<1)&0X7F;
	dat = 0x03;
	addr |= ParityCheck(addr)^ParityCheck(dat);  // 异或
	MCT8316_write_reg(addr,dat);
	HAL_Delay(10);
	
	
	addr = (Control_Register_2A<<1)&0X7F;
	dat = 0x03;
	addr |= ParityCheck(addr)^ParityCheck(dat);  // 异或
	MCT8316_write_reg(addr,dat);
	HAL_Delay(10);
	
	addr = (Control_Register_3<<1)&0X7F;
	dat = 0x04E;
	addr |= ParityCheck(addr)^ParityCheck(dat);  // 异或
	MCT8316_write_reg(addr,dat);
	HAL_Delay(10);
	
	addr = (Control_Register_4<<1)&0X7F;
	dat = 0x10;
	addr |= ParityCheck(addr)^ParityCheck(dat);  // 异或
	MCT8316_write_reg(addr,dat);
	HAL_Delay(10);
	
	addr = (Control_Register_5<<1)&0X7F;
	dat = 0x00;
	addr |= ParityCheck(addr)^ParityCheck(dat);  // 异或
	MCT8316_write_reg(addr,dat);
	HAL_Delay(10);
	
	addr = (Control_Register_6<<1)&0X7F;
	dat = 0x12; // 0X12-5V
	addr |= ParityCheck(addr)^ParityCheck(dat);  // 异或
	MCT8316_write_reg(addr,dat);
	HAL_Delay(10);
	
	addr = (Control_Register_7<<1)&0X7F;
	dat = 0x01;
	addr |= ParityCheck(addr)^ParityCheck(dat);  // 异或
	MCT8316_write_reg(addr,dat);
	HAL_Delay(10);
	
	addr = (Control_Register_8<<1)&0X7F;
	dat = 0x01;
	addr |= ParityCheck(addr)^ParityCheck(dat);  // 异或
	MCT8316_write_reg(addr,dat);
	HAL_Delay(10);
	
	addr = (Control_Register_9<<1)&0X7F;
	dat = 0x00;
	addr |= ParityCheck(addr)^ParityCheck(dat);  // 异或
	MCT8316_write_reg(addr,dat);
	HAL_Delay(10);
	
	addr = (Control_Register_10<<1)&0X7F;
	dat = 0x03;
	addr |= ParityCheck(addr)^ParityCheck(dat);  // 异或
	MCT8316_write_reg(addr,dat);
	HAL_Delay(10);	
	
	
	status[0] = MCT8316_read_reg(IC_Status_Register);   // 读取IC状态寄存器
	status[1] = MCT8316_read_reg(Status_Register_1);  // 读取IC状态寄存器
	status[2] = MCT8316_read_reg(Status_Register_2);   // 读取IC状态寄存器
	
	status[3] = MCT8316_read_reg(Control_Register_4);   // 读取IC状态寄存器
	status[4] = MCT8316_read_reg(Control_Register_5);   // 读取IC状态寄存器
	status[5] = MCT8316_read_reg(Control_Register_6);   // 读取IC状态寄存器
	status[6] = MCT8316_read_reg(Control_Register_7);   // 读取IC状态寄存器
	status[7] = MCT8316_read_reg(Control_Register_8);   // 读取IC状态寄存器
	status[8] = MCT8316_read_reg(Control_Register_9);   // 读取IC状态寄存器
	status[9] = MCT8316_read_reg(Control_Register_10);  // 读取IC状态寄存器
	
}

void SetUp(void)
{
	
	addr = (Control_Register_1<<1)&0X7F;
	dat = 0x03;
	addr |= ParityCheck(addr)^ParityCheck(dat);  // 异或
	MCT8316_write_reg(addr,dat);
	HAL_Delay(10);
	
	addr = (Control_Register_2A<<1)&0X7F;
	dat = 0x02;
	addr |= ParityCheck(addr)^ParityCheck(dat);  // 异或
	MCT8316_write_reg(addr,dat);
	HAL_Delay(10);
}

// data: 待校验数据
// return:data中1的数目为奇数,返回true,否则返回false。
uint8_t ParityCheck(uint8_t data)
{
    uint8_t parity = 0;
    while (data)
    {
        parity = !parity;
        data &= data - 1;
    }
    return parity;
}

  MCT8316ZR.h

#ifndef MCT8316_H
#define MCT8316_H

#include "stm32L4xx_hal.h"

#define     ICM20602_SPI_WRITE              0x00
#define     ICM20602_SPI_READ               0x80

// 只读状态寄存器
#define	IC_Status_Register				0x00
#define	Status_Register_1 				0x01
#define	Status_Register_2 				0x02
// 控制寄存器
#define	Control_Register_1				0x03
#define	Control_Register_2A				0x04
#define	Control_Register_3				0x05
#define	Control_Register_4				0x06
#define	Control_Register_5				0x07
#define	Control_Register_6				0x08
#define	Control_Register_7				0x09
#define	Control_Register_8				0x0A
#define	Control_Register_9				0x0B
#define	Control_Register_10				0x0C


#define  MOSI_H  HAL_GPIO_WritePin(GPIOE, motor_2_MOSI_Pin, GPIO_PIN_SET)
#define  MOSI_L  HAL_GPIO_WritePin(GPIOE, motor_2_MOSI_Pin, GPIO_PIN_RESET)

#define  SCK_H   HAL_GPIO_WritePin(GPIOE, motor_2_CLK_Pin, GPIO_PIN_SET)
#define  SCK_L   HAL_GPIO_WritePin(GPIOE, motor_2_CLK_Pin, GPIO_PIN_RESET)

#define  MISO    HAL_GPIO_ReadPin(GPIOE, motor_2_MISO_Pin)
// #define  MISO  HAL_GPIO_WritePin(GPIOE, motor_2_MOSI_Pin, GPIO_PIN_RESET)

#define  SCK_H  HAL_GPIO_WritePin(GPIOE, motor_2_CLK_Pin, GPIO_PIN_SET)
#define  SCK_L  HAL_GPIO_WritePin(GPIOE, motor_2_CLK_Pin, GPIO_PIN_RESET)

uint8_t MCT8316_read_buffer(uint8_t const regAddr, uint8_t *pData, uint8_t len);
uint8_t MCT8316_write_reg(uint8_t reg,uint8_t val);
uint8_t MCT8316_read_reg(uint8_t reg);
void MCT8316_Init(void);

uint8_t ParityCheck(uint8_t data);

void A_MCT8316_Init(void);
void SetUp(void);
void SPI_Write(SPI_HandleTypeDef* hspi,uint16_t address, uint16_t data);
uint8_t parityCheck_write(uint8_t regAddr, uint8_t data);
uint8_t SPI_Read(SPI_HandleTypeDef* hspi,uint16_t address);
uint8_t parityCheck_read(uint8_t regAddr);


// 模拟SPI四种发送方式:
uint16_t SOFT_SPI_RW_MODE0(uint16_t write_dat);
uint16_t SOFT_SPI_RW_MODE1(uint16_t byte);
uint16_t SOFT_SPI_RW_MODE2(uint16_t byte);
uint16_t SOFT_SPI_RW_MODE3(uint16_t write_dat );

// 延时us函数
void delay_us(uint32_t nus);

#endif

六、往期回顾

项目进展(一)-晶振正常输出、焊接驱动芯片、查找芯片手册并学习
项目进展(二)-配置MCT8316ZR芯片,主要学习如何根据数据手册配置外设等
项目进展(三)-电机驱动起来了,发现了很多关键点,也遇到了一些低级错误

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

致虚守静~归根复命

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值