如何使用STM32微控制器通过SPI接口配置LMX2820芯片

发布于:2025-02-20 ⋅ 阅读:(36) ⋅ 点赞:(0)

参考资料:
正点原子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或者单片机引脚。
以下是实验效果:
在这里插入图片描述