stm32f405通过SPI控制24bitsDAC芯片的代码

最近使用到DAC芯片,目的是通过stm32f4控制板控制该芯片输出想要的电压,芯片的通信接口是SPI,一次需要发送24bits的数据才行,但是stm32f4的SPI硬件只有8bits和16bits两种选择,所以没法用硬件来实现,只能通过软件SPI模拟口来实现。

SPI通信接口主要包括4根引线,即MOSI,MISO,SCLK,CS。MOSI是主设备输出从设备输入,MISO是从设备输出主设备输入,SCLK是时钟线,用于同步时钟,而CS是片选信号,用于选择通讯设备。SPI通信中必须包含至少一台主设备,且只有主设备才能发起通讯,而允许存在多台从设备,对于存在多台从设备的情况,可通过从设备的CS引脚选择从设备。

                  

SPI通讯是由时钟线发起的,且只有主设备才能控制时钟线电平的高低,在STM32F4中,当设置CPOL=1时,表示时钟线处于高电平时是空闲状态;CPOL=0时,表示时钟线处于低电平时为空闲状态。当设置CPHA=0时,表示在时钟第一个跳变沿的时候开始采样,而当CPHA=1时,表示在时钟第二个跳变沿时才开始采样。

总的来说,SPI的通讯过程是这样的,以低电平为空闲状态为例,且在第一个跳变沿开始采样(硬件SPI需要设置这两个设定,但软件SPI就不需要,软件SPI的话,主要是看你从设备,也就是DAC芯片是什么样设置,DAC芯片手册如何要求就如何写即可)。我使用的芯片就是低电平空闲,且在第一个跳变沿开始采样。

我的SPI任意使用了PB10,PB11,PB12,PB13四个接口,于是

PB15 ——推挽上拉电阻输出, 对应MOSI

PB14 ——开漏输入, 对应MISO

PB13 ——推挽上拉电阻输出,   对应SCLK

PB12 ——推挽上拉电阻输出, 对应CS

主设备和从设备之间是通过SCLK线来同步消息的,在SCLK线低电平时表示空闲,而在高电平时,从设备会检测MOSI线路上的电平,高低电平表示要发送的数据,因此在SCLK变为高电平时,需要MOSI线上的电平保持稳定。而MOSI的电平由主设备来控制。因此,假设我们要发一个24bits的数据,例如0xffffff,则第一步需要将SCLK拉低,stm32f4中用函数GPIO_ResetBits(GPIOB,GPIO_Pin_13),第二步查看要发送的首位数据是1还是0,0xffffff最高位是1,因此接下来要发送的是高电平,可用GPIO_SetBits(GPIOB,GPIO_Pin_15),将MOSI置高,第三步,拉高SCLK线,从设备接收数据,就是GPIO_SetBits(GPIOB,GPIO_Pin_13),延迟2us,再将SCLK线拉低,这样就实现了一位数据的传输。下面给一个具体的代码。

void SPI2_Init(void)   //IO口设置
{     
  GPIO_InitTypeDef  GPIO_InitStructure;
  GPIO_InitTypeDef  GPIO_InitStructure1;
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);//使能GPIOB时钟
 
    GPIO_InitStructure1.GPIO_Pin = GPIO_Pin_14;//PB14输入     
  GPIO_InitStructure1.GPIO_Mode = GPIO_Mode_IN;//普通输入功能
  GPIO_InitStructure1.GPIO_OType = GPIO_OType_OD;//开漏
  GPIO_InitStructure1.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
  GPIO_InitStructure1.GPIO_PuPd = GPIO_PuPd_NOPULL;
  GPIO_Init(GPIOB, &GPIO_InitStructure1);//初始化

  //GPIOFB13,12,15初始化设置
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13|GPIO_Pin_12|GPIO_Pin_15;//PB12,13,15复用功能输出    
  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(GPIOB, &GPIO_InitStructure);//初始化

}

 

 

void SPI_Send(u32 data)                                              //与DAC通信,dac发送数据是固定24bits的
{
    int i=0;
    GPIO_ResetBits(GPIOB,GPIO_Pin_12);                 //CS线,拉低选中从设备
    for(i=0;i<24;i++)
    {        
        if(data&0x00800000)                                           //取数据的最高位,一般是从最高位开始发
        {
            GPIO_SetBits(GPIOB,GPIO_Pin_15);             //如果是1,将MOSI拉高
        }
        else 
        {
            GPIO_ResetBits(GPIOB,GPIO_Pin_15);          //如果是0,将MOSI拉低
        }
        GPIO_SetBits(GPIOB,GPIO_Pin_13);                  //拉高SCLK线
        delay_us(2);
        GPIO_ResetBits(GPIOB,GPIO_Pin_13);               //拉低SCLK线
        data=data<<1;                                                       //向左移位,发送下一位数据
    }
     GPIO_SetBits(GPIOB,GPIO_Pin_12);                      //CS线拉高,结束传输
}

 

STM32F405系列微控制器通常使用HAL库来简化SPI(Serial Peripheral Interface)的配置。以下是使用 HAL SpiModule_Init 函数的基本步骤: ```c #include "stm32f4xx_hal.h" // 假设 spi1是你要配置的SPI实例 SPI_HandleTypeDef hi SpiHandle; void SPI_Config(void) { // 配置SPI时钟源和波特率 RCC_APB1PeriphClockCmd(RCC_APB1Periph_GPIOA | RCC_APB1Periph_AFIO, ENABLE); // 驱动GPIOA用于数据线 GPIO_InitTypeDef GPIO_InitStruct; GPIO_InitStruct.Pin = GPIO_PIN_9 | GPIO_PIN_10; // 数据线PA9和PA10 GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; //推挽模式 GPIO_InitStruct.Pull = GPIO_NOPULL; //无上拉 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF7_SPI1; // 设置AF7为SPI1的组别 GPIO_Init(GPIOA, &GPIO_InitStruct); // 初始化SPI Handle SpiHandle.Instance = SPI1; SpiHandle.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_8; // 波特率分频系数 SpiHandle.Init.Direction = SPI_DIRECTION_2LINES; // 半双工模式 SpiHandle.Init.DataSize = SPI_DATASIZE_8BIT; // 8数据宽度 SpiHandle.Init.CLKPolarity = SPI_POLARITY_LOW; // 针脚CPOL电平低 SpiHandle.Init.CLKPhase = SPI_PHASE_1EDGE; // CPHA=1边缘触发 SpiHandle.Init.CRCPolynomial = 7; // CRC校验使用CRC7 SpiHandle.Init.FirstBit = SPI_FIRSTBIT_MSB; // MSB发送 if (HAL SpiModule_Init(&SpiHandle) != HAL_OK) { while(1); // 初始化失败,进入无限循环 } // 如果需要使能SPI模块,可以在这里设置 HAL Spi_MspInit(&SpiHandle); }
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值