参考资料:
正点原子SPI通讯相关代码
LMX2594驱动编程
LMX2571 芯片配置Verliog SPI驱动
所使用芯片:STM32F407
SPI相关设置参考正点原子:
#include "./BSP/SPI/spi.h"
#include "./SYSTEM/delay/delay.h"/*** @brief SPI初始化代码* @note 主机模式,8位数据,禁止硬件片选* @param 无* @retval 无*/
void spi1_init(void)
{uint32_t tempreg = 0;SPI1_SPI_CLK_ENABLE(); /* SPI1时钟使能 */SPI1_SCK_GPIO_CLK_ENABLE(); /* SPI1_SCK脚时钟使能 */SPI1_SDI_GPIO_CLK_ENABLE(); /* SPI1_MOSI脚时钟使能 */sys_gpio_set(SPI1_SCK_GPIO_PORT, SPI1_SCK_GPIO_PIN,SYS_GPIO_MODE_AF, SYS_GPIO_OTYPE_PP, SYS_GPIO_SPEED_HIGH, SYS_GPIO_PUPD_PU); /* SCK引脚模式设置(复用输出) */sys_gpio_set(SPI1_SDI_GPIO_PORT, SPI1_SDI_GPIO_PIN,SYS_GPIO_MODE_AF, SYS_GPIO_OTYPE_PP, SYS_GPIO_SPEED_HIGH, SYS_GPIO_PUPD_PU); /* SDI引脚模式设置(复用输出) */sys_gpio_af_set(SPI1_SCK_GPIO_PORT, SPI1_SCK_GPIO_PIN, SPI1_SCK_GPIO_AF); /* SCK脚, AF功能设置 */sys_gpio_af_set(SPI1_SDI_GPIO_PORT, SPI1_SDI_GPIO_PIN, SPI1_SDI_GPIO_AF); /* SDI脚, AF功能设置 */tempreg |= 0 << 11; /* DFF = 0 , 使用8位数据格式 */tempreg |= 0 << 10; /* RXONLY = 0 , 全双工模式 */tempreg |= 1 << 9; /* SSM = 1 , 软件片选(NSS)控制 */tempreg |= 1 << 8; /* SSI = 1 , 禁止软件从设备, 即做主机 */tempreg |= 0 << 7; /* LSBFRST = 0 , MSB先传输 */tempreg |= 7 << 3; /* BR[2:0] = 7 , 默认使用256分频, 速度最低 */tempreg |= 1 << 2; /* MSTR = 1 , 主机模式 */tempreg |= 0 << 1; /* CPOL = 0 , 空闲状态下, SCK保持低电平 */tempreg |= 0 << 0; /* CPHA = 0 , 数据采集从第一个时钟边沿开始 */SPI1_SPI->CR1 = tempreg; /* 设置CR1寄存器 */SPI1_SPI->CR1 |= 1 << 6; /* SPE = 1 , 使能SPI */}/*** @brief SPI1速度设置函数* @note SPI1时钟选择来自APB2, 即PCLK2, 为84Mhz* SPI速度 = PCLK2 / 2^(speed + 1)* @param speed : SPI1时钟分频系数* @retval 无*/
void spi1_set_speed(uint8_t speed)
{speed &= 0X07; /* 限制范围 */SPI1_SPI->CR1 &= ~(1 << 6); /* SPE = 0 , SPI设备失能 */SPI1_SPI->CR1 &= ~(7 << 3); /* BR[2:0] = 0 , 先清零 */SPI1_SPI->CR1 |= speed << 3; /* BR[2:0] = speed , 设置分频系数 */SPI1_SPI->CR1 |= 1 << 6; /* SPE = 1 , SPI使能 */
}/*** @brief SPI1读写一个字节数据* @param txdata : 要发送的数据(1字节)* @retval 接收到的数据(1字节)*/
uint32_t spi1_write_byte(uint32_t txdata)
{while ((SPI1_SPI->SR & 1 << 1) == 0); /* 等待发送区空 */SPI1_SPI->DR = txdata; /* 发送一个byte */while ((SPI1_SPI->SR & 1 << 0) == 0); /* 等待接收完一个byte */return SPI1_SPI->DR; /* 返回收到的数据 */
}
lmx2820代码:
#include "stm32f4xx.h"
#include "./BSP/LMX2820/lmx2820.h"
#include "./SYSTEM/delay/delay.h"
#include "./BSP/SPI/spi.h"
#include "./SYSTEM/sys/sys.h"
#include "./SYSTEM/usart/usart.h"#define LMX2820_CONIG_REG_CNT 123
uint32_t config_arr[LMX2820_CONIG_REG_CNT]={0x7A0000,0x790000,0x780000,0x770000,0x760000,0x750000,0x740000,0x730000,0x720000,0x710000,0x70FFFF,0x6F0000,0x6E001F,0x6D0000,0x6C0000,0x6B0000,0x6A0000,0x69000A,0x680014,0x670014,0x660028,0x6503E8,0x640533,0x6319B9,0x621C80,0x610000,0x6017F8,0x5F0000,0x5E0000,0x5D1000,0x5C0000,0x5B0000,0x5A0000,0x590000,0x5803FF,0x57FF00,0x560040,0x550000,0x540040,0x530F00,0x520000,0x510000,0x5001C0,0x4F0112,0x4E0000,0x4D0608,0x4C0000,0x4B0101,0x4A8A25,0x490000,0x480000,0x470000,0x46000E,0x450001,0x440000,0x435000,0x42003F,0x410001,0x400088,0x3FC350,0x3E0000,0x3D03E8,0x3C01F4,0x3B1388,0x3A0000,0x390001,0x380001,0x370002,0x360000,0x350000,0x340000,0x33203F,0x320080,0x310000,0x304180,0x2F0300,0x2E0300,0x2D0000,0x2C0000,0x2B0000,0x2A0000,0x290000,0x280000,0x2703E8,0x260000,0x250500,0x240078,0x233100,0x220010,0x210000,0x201081,0x1F0401,0x1EB18C,0x1D318C,0x1C0639,0x1B8001,0x1A0DB0,0x190624,0x180E34,0x171102,0x16E2BF,0x151C64,0x14272C,0x132120,0x120000,0x1115C0,0x10171C,0x0F2001,0x0E3001,0x0D0038,0x0C0408,0x0B0602,0x0A0000,0x090005,0x08C802,0x070000,0x060A43,0x050032,0x044204,0x030041,0x0280FA,0x0157A0,0x006070};void LMX2820_SPI_Init(void)
{LMX2820_CS_GPIO_CLK_ENABLE(); /* LMX2820 CS脚 时钟使能 */sys_gpio_set(LMX2820_CS_GPIO_PORT, LMX2820_CS_GPIO_PIN,SYS_GPIO_MODE_OUT, SYS_GPIO_OTYPE_PP, SYS_GPIO_SPEED_HIGH, SYS_GPIO_PUPD_PU); /* CS引脚模式设置(复用输出) */LMX2820_CS(1); /* 取消片选 */spi1_init(); /* 初始化SPI1 */spi1_set_speed(SPI_SPEED_256); /* SPI1 切换到高速状态 */}/*** @brief LMX2820发送数据* @note 根据芯片型号的不同, 发送24ibt / 32bit地址* @param address : 要发送的地址* @retval 无*/
static void LMX2820_send_address(uint32_t address)
{spi1_write_byte((uint8_t)((address)>>16)); /* 发送 bit23 ~ bit16 地址 */spi1_write_byte((uint8_t)((address)>>8)); /* 发送 bit15 ~ bit8 数据 */spi1_write_byte((uint8_t)address); /* 发送 bit7 ~ bit0 数据 */
}/*寄存器写入*/
void LMX2820_write(uint32_t data)
{uint32_t txData = 0;LMX2820_CS(0);txData = data;LMX2820_send_address(txData);LMX2820_CS(1);delay_us(3);}/*LMX2820初始化*/
void LMX2820_init(void)
{for(uint8_t i = 0;i < LMX2820_CONIG_REG_CNT; i++){if(i % 16 == 0){delay_ms(10);}LMX2820_write(config_arr[i]);}}
注意,lmx2820芯片CE引脚需要连接3.3V或者单片机引脚。
以下是实验效果: