一、前言
截止到今天,该项目也算实现基本功能了,后续继续更新有关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芯片,主要学习如何根据数据手册配置外设等
项目进展(三)-电机驱动起来了,发现了很多关键点,也遇到了一些低级错误