疯影17 发表于 2017-11-5 22:28:40

STM32F410RB HAL SPI驱动数码管模块,求指导

本帖最后由 疯影17 于 2017-11-5 23:00 编辑

新手上路,请教了{:3_41:}
开发板用的 NUCLEO-f410rb ,数码管用的4位共阳极的能串联的静态显示模块。

首先配置spi2模式为“全双工主模式”
连线
STM32 -> 数码管
SPI2_MOSI -> SDI
SPI2_SCK -> SCLK
SPI2_LOAD -> LOAD
5V -> VCC
GND -> GND
SPI2_MOSI是SPI2主机输出, SPI2_SCK是主机时钟,其中SPI2_LOAD是普通引脚PA5,只用了这三个引脚。主机输入没用,因为数码管驱动不需要。

在main.c文件中添加两个变量
/* USER CODE BEGIN PV */
/* Private variables ---------------------------------------------------------*/
uint16_t add_num = 0;
uint8_t data[] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e,0x7f};// 数码管的段码0-f 最后一位0x7f是小数点

/* USER CODE END PV */led.h头文件
#ifndef LED_H
#define LED_H

/* Includes ------------------------------------------------------------------*/
#include "stm32f4xx_hal.h"
#include "main.h"

/* 数码管位枚举 */
typedef enum{
    GE_BIT,
    SHI_BIT,
    BAI_BIT,
    QIAN_BIT
}LedBIT;
extern uint8_t data[];
extern SPI_HandleTypeDef hspi2;
void hc74959_display(uint16_t num);
#endif
led.c
#include "led.h"


/* 数码管显示函数 spi2驱动
*数码管模块是74hc595驱动的,静态显示所以有每位数码管单独一个74hc595
*/
void hc74959_display(uint16_t num){

    uint16_t qian = num / 1000;   // 解析后的千位数字
    uint16_t bai = num / 100 % 10;// 解析后的百位数字
    uint16_t shi = num /10 %10;   // 解析后的十位数字
    uint16_t ge = num %10;          // 解析后的个位数字

    for (uint8_t j=0;j<4;j++){
      
      switch (j){
      case GE_BIT:
          // 个位
          HAL_SPI_Transmit(&hspi2, &data, 1, 1000);   // SPI 输出
          break;
      case SHI_BIT:
          // 十位
          HAL_SPI_Transmit(&hspi2, &data, 1, 1000);
          break;
      case BAI_BIT:
          // 百位
          HAL_SPI_Transmit(&hspi2, &data, 1, 1000);
          break;
      case QIAN_BIT:
          // 千位
          HAL_SPI_Transmit(&hspi2, &data, 1, 1000);
          break;
      default:
          break;
      }
    } // end for

    /* 让锁存输出一个高电平脉冲 */
    HAL_GPIO_WritePin(SPI2_LOAD_GPIO_Port, SPI2_LOAD_Pin, GPIO_PIN_SET);
    HAL_Delay(10);
    HAL_GPIO_WritePin(SPI2_LOAD_GPIO_Port, SPI2_LOAD_Pin, GPIO_PIN_RESET);
} /* end --------- hc74959_display functions ---------------- */
main.c 文件中的主循环
while (1)
{
/* USER CODE END WHILE */

/* USER CODE BEGIN 3 */
    HAL_Delay(1000); // 每隔1秒add_num加1
    add_num ++;
    if (add_num >=1000){// 当add_num 大于1000时,从新赋值为0
      add_num = 0;
    }
    hc74959_display(add_num); 调用led.c中的数码管显示函数
   
}
/* USER CODE END 3 */以上是所有代码。

最主要的是SPI的发送数据函数HAL_SPI_Transmit(&hspi2, &data, 1, 1000);,使用方法对不对,第三个参数的意思不是很明白。
配置的是全双工主模式,但是用的HAL_SPI_Transmit()是发送函数,会不会有什么影响?
HAL_SPI_Transmit()是最后的驱动数码管的选择吗?

逻辑分析仪的显示情况


看显示状况是没什么问题。



liming-367095 发表于 2017-11-7 09:48:09

支持一下 :)

MrJiu 发表于 2017-11-7 11:33:01

驱动数码管是啥芯片?

zero99 发表于 2017-11-20 16:55:54

楼主下次请发求助帖!

toofree 发表于 2018-3-8 01:29:29

本帖最后由 toofree 于 2018-3-8 01:34 编辑

HAL_SPI_Transmit(&hspi2, &data, 1, 1000);

原型是这样的,
HAL_StatusTypeDef HAL_SPI_Transmit(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size, uint32_t Timeout)。

第三个参数是一次要连续发送的数据个数;第四个参数为最大延时时间,单元为us。
假设SPI时钟为1MHz,即1us;发送的数据长度Size为N,发送数据类型为uint8_t,那么一共要传输 N*8位。
整个传输时间就是 1us * N * 8位 =8N us,那么这个Timeout的时间就设为 N*8 us。如果数据类型是uint16_t,那么延时就是 N*16 us

jjbboox 发表于 2018-3-8 11:03:15

Timeout是ms单位的,根本无所谓的,一般直接设为0xFFFF就行了。
另外不用1个字节1个字节发,可以4个字节一起发
HAL_SPI_Transmit(&hspi2, data, 4, 0xFFFF);

还有就是不用设为全双工的,设为master_transmit就可以了,你只发不收的。没必要全双工。
数据发送完毕,在LOAD端口给个信号就会把数字显示出来了。

疯影17 发表于 2018-4-4 18:41:27

jjbboox 发表于 2018-3-8 11:03
Timeout是ms单位的,根本无所谓的,一般直接设为0xFFFF就行了。
另外不用1个字节1个字节发,可以4个字节一 ...

知道了,确实是只发送就够了:lol

疯影17 发表于 2018-4-4 19:53:12

MrJiu 发表于 2017-11-7 11:33
驱动数码管是啥芯片?

74hc595

MrJiu 发表于 2018-4-5 09:37:18

jjbboox 发表于 2018-3-8 11:03
Timeout是ms单位的,根本无所谓的,一般直接设为0xFFFF就行了。
另外不用1个字节1个字节发,可以4个字节一 ...

0xffff肯定是不行的。。。万一SPI错误,会导致程序卡死在那个SPI传输里!!!

jjbboox 发表于 2018-4-6 10:09:44

本帖最后由 jjbboox 于 2018-4-6 10:11 编辑

MrJiu 发表于 2018-4-5 09:37
0xffff肯定是不行的。。。万一SPI错误,会导致程序卡死在那个SPI传输里!!! ...
不会卡死的,0xffff也不是什么大数字,也就是65秒,像类似的应用,发送不会失败的,所以这里随便设一个值就行了,除非你要发送一个巨大的数量,确定多少ms内无法发送完成,那么尽量设一个大一点的通常没啥毛病。一般都用DMA或者IT方式发送,都不需要设这个TIMEOUT的。
页: [1] 2
查看完整版本: STM32F410RB HAL SPI驱动数码管模块,求指导