硬件探索——STM32F4通过SPI总线读取GMR(磁编码器)

使用STM32F407VET6,通过SPI串行总线读取GMR(磁编码器)的相关数据(速度、角度绝对值等)

使用了PC10(SCK)、PC11(MISO)、PC12(MOSI)、PA15(CS)四个GPIO,将其与编码器对应连接

程序中使用了延时函数,需要包含系统滴答定时器延时函数使用的头文件delay.h

头文件spi.h

#ifndef __SPI_H__
#define __SPI_H__
#include "sys.h"

#define SPI3_PORT             GPIOC
#define SPI3_PIN             (GPIO_Pin_10|GPIO_Pin_11|GPIO_Pin_12)
#define SPI3_PORT_RCC         RCC_AHB1Periph_GPIOC

void SPI3_Init(void); //初始化SPI3
uint16_t SPI3_ReadWriteByte(uint16_t TxData); //SPI3总线读写一个字节
		 
#endif

源文件spi.c

#include "spi.h"

void SPI3_Init()
{
    GPIO_InitTypeDef GPIO_InitStructure;
    SPI_InitTypeDef  SPI_InitStructure;

    RCC_AHB1PeriphClockCmd(SPI3_PORT_RCC, ENABLE);      //使能GPIO时钟
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI3, ENABLE);//使能SPI3外设时钟(SPI3挂载于内部低速总线APB1,最高84MHz)

    //GPIO初始化设置
    GPIO_InitStructure.GPIO_Pin = SPI3_PIN;            //PC10~12使用复用功能输出
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;       //复用功能
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;     //推挽输出
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; //100MHz
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;       //上拉
    GPIO_Init(SPI3_PORT, &GPIO_InitStructure);         //初始化
    //GPIO复用功能设置
    GPIO_PinAFConfig(SPI3_PORT, GPIO_PinSource10, GPIO_AF_SPI3); //PC10复用为 SPI3_SCK
    GPIO_PinAFConfig(SPI3_PORT, GPIO_PinSource11, GPIO_AF_SPI3); //PC11复用为 SPI3_MISO
    GPIO_PinAFConfig(SPI3_PORT, GPIO_PinSource12, GPIO_AF_SPI3); //PC12复用为 SPI3_MOSI

    RCC_APB1PeriphResetCmd(RCC_APB1Periph_SPI3, ENABLE); //复位SPI3
    RCC_APB1PeriphResetCmd(RCC_APB1Periph_SPI3, DISABLE);//停止复位SPI3
    //SPI相关参数设置
    SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;  //设置SPI单向或者双向的数据模式:双线双向全双工
    SPI_InitStructure.SPI_Mode = SPI_Mode_Master;		//设置SPI工作模式:设置为SPI主机
    SPI_InitStructure.SPI_DataSize = SPI_DataSize_16b;  //设置SPI的数据大小:SPI发送接收16位帧结构
    SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;		    //串行同步时钟的空闲状态:低电平
    SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;	    //串行同步时钟的第二个跳变沿(上升或下降)数据被采样
    SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;		    //NSS信号由软件(使用SSI位)管理,内部NSS信号由SSI位控制
    SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256; //定义波特率预分频的值为256
    SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;	//指定数据传输从MSB位还是LSB位开始:数据传输从MSB位开始
    SPI_InitStructure.SPI_CRCPolynomial = 7;	        //CRC值计算(若有)的多项式
    SPI_Init(SPI3, &SPI_InitStructure);                 //根据SPI_InitStruct中指定的参数初始化外设SPI3寄存器

    SPI_Cmd(SPI3, ENABLE);     //使能SPI3外设

    SPI3_ReadWriteByte(0xffff);//发送全"1",启动传输
}

//SPI3读写数据
//TxData:要写入的数据
//返回值:读取到的数据
uint16_t SPI3_ReadWriteByte(uint16_t TxData)
{

    while (SPI_I2S_GetFlagStatus(SPI3, SPI_I2S_FLAG_TXE) == RESET) {} //等待发送区空

    SPI_I2S_SendData(SPI3, TxData);   //通过外设SPI3发送一个16bit数据

    while (SPI_I2S_GetFlagStatus(SPI3, SPI_I2S_FLAG_RXNE) == RESET) {}//等待16bit数据接收完成

    return SPI_I2S_ReceiveData(SPI3); //返回通过SPI3最近接收的数据
}

 头文件gmr.h

#ifndef __GMR_H__
#define __GMR_H__
#include "sys.h"

#define CS_PORT             GPIOA
#define CS_PIN             (GPIO_Pin_15)
#define CS_PORT_RCC         RCC_AHB1Periph_GPIOA

#define SPI3_CS PAout(15)

/* SPI command for TLE5012 */
#define READ_STATUS			    0x8001			//8000
#define READ_ANGLE_VALUE		0x8021			//8020
#define READ_SPEED_VALUE		0x8031			//8030

#define WRITE_MOD1_VALUE		0x5060							//0_1010_0_000110_0001
#define MOD1_VALUE	0x0001

#define WRITE_MOD2_VALUE		0x5080							//0_1010_0_001000_0001
#define MOD2_VALUE	0x0801

#define WRITE_MOD3_VALUE		0x5091							//0_1010_0_001001_0001
#define MOD3_VALUE	0x0000

#define WRITE_MOD4_VALUE		0x50E0							//0_1010_0_001110_0001
#define MOD4_VALUE	0x0098		//9bit 512

#define WRITE_IFAB_VALUE		0x50B1
#define IFAB_VALUE 0x000D
/* Functionality mode */
#define REFERESH_ANGLE		0

void GMR_Init(void);
uint16_t ReadAngle1(void);
float Conversion_Speed1(void);
short ReadSpeed1(void);
uint16_t ReadValue1(uint16_t u16RegValue);

#endif

 源文件gmr.c

#include "gmr.h"
#include "spi.h"

GPIO_InitTypeDef GPIO_InitStructure_SPI;

void GMR_Init()
{
    GPIO_InitTypeDef GPIO_InitStructure;//定义结构体变量

    RCC_AHB1PeriphClockCmd(CS_PORT_RCC, ENABLE);

    GPIO_InitStructure.GPIO_Pin = CS_PIN;              //要设置的IO口
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;      //普通输出模式
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;     //推挽输出
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; //100MHz
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;       //上拉
    GPIO_Init(CS_PORT, &GPIO_InitStructure); 	       /* 初始化GPIO */

    GPIO_SetBits(CS_PORT, CS_PIN);  //将片选端口拉高

    /* 以下代码初始化SPI接口的读写 */
    GPIO_InitStructure_SPI.GPIO_Pin = GPIO_Pin_12;   //PC12复用功能输出
    GPIO_InitStructure_SPI.GPIO_Mode = GPIO_Mode_AF; //使用复用功能
    GPIO_InitStructure_SPI.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
    GPIO_InitStructure_SPI.GPIO_PuPd = GPIO_PuPd_UP;      //上拉
}

uint16_t ReadValue1(uint16_t u16RegValue)
{
    uint16_t u16Data;

    SPI3_CS = 0;

    SPI3_ReadWriteByte(u16RegValue);
    //SPI_TX_OFF;将主设备数据输出,从设备数据输入(MOSI)配置成开漏--输入模式
    GPIO_InitStructure_SPI.GPIO_OType = GPIO_OType_OD;//开漏输出
    GPIO_Init(SPI3_PORT, &GPIO_InitStructure_SPI);//初始化

    //发送 0xFFFF 是无用的,可能是为了有时钟
    u16Data = (SPI3_ReadWriteByte(0xffff) & 0x7FFF);//0x12/0xff*100k

    SPI3_CS = 1;
    //SPI_TX_ON;将主设备数据输出,从设备数据输入(MOSI)配置成推挽--输出模式
    GPIO_InitStructure_SPI.GPIO_OType = GPIO_OType_PP;//推挽输出
    GPIO_Init(SPI3_PORT, &GPIO_InitStructure_SPI);//初始化

    return(u16Data);
}

short ReadSpeed1()
{
    short Data;

    Data = (short)(ReadValue1(READ_SPEED_VALUE) << 1) >> 1;

    return Data;
}

float Conversion_Speed1()
{
    float Speed;
    Speed = ((float)(ReadSpeed1() * 360) / 65535) / (2 * 0.0000213); //单位°/s;
    return (Speed / (float)360.0); //返回每秒的转数
}

uint16_t ReadAngle1()
{
    return ((ReadValue1(READ_ANGLE_VALUE) << 1) * 360 / 0x10000);
}

 使用实例如下:

#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "spi.h"
#include "gmr.h"

int main(void)
{
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2
    delay_init(168);     //初始化延时函数
    uart_init(115200);	 //初始化串口波特率为115200
    GMR_Init();
    SPI3_Init();
    while (1)
    {
        delay_ms(5);
        printf("speed:%d\r\n", ReadSpeed1());
        printf("angle:%d\r\n", ReadAngle1());
    }
}

效果如下:

硬件探索——STM32F4通过SPI总线读取GMR(磁编码器)_第1张图片

你可能感兴趣的:(Hardware,stm32,编码器,GMR,spi)