你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

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

[复制链接]
疯影17 提问时间:2017-11-5 22:28 /
本帖最后由 疯影17 于 2017-11-5 23:00 编辑

新手上路,请教了
开发板用的 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文件中添加两个变量
  1. /* USER CODE BEGIN PV */
  2. /* Private variables ---------------------------------------------------------*/
  3. uint16_t add_num = 0;
  4. uint8_t data[] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e,0x7f};  // 数码管的段码0-f 最后一位0x7f是小数点

  5. /* USER CODE END PV */
复制代码
led.h头文件
  1. #ifndef LED_H
  2. #define LED_H

  3. /* Includes ------------------------------------------------------------------*/
  4. #include "stm32f4xx_hal.h"
  5. #include "main.h"

  6. /* 数码管位枚举 */
  7. typedef enum{
  8.     GE_BIT,
  9.     SHI_BIT,
  10.     BAI_BIT,
  11.     QIAN_BIT
  12. }LedBIT;
  13. extern uint8_t data[];
  14. extern SPI_HandleTypeDef hspi2;
  15. void hc74959_display(uint16_t num);
  16. #endif
复制代码

led.c
  1. #include "led.h"


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

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

  10.     for (uint8_t j=0;j<4;j++){
  11.       
  12.       switch (j){
  13.         case GE_BIT:
  14.           // 个位
  15.           HAL_SPI_Transmit(&hspi2, &data[ge], 1, 1000);     // SPI 输出
  16.           break;
  17.         case SHI_BIT:
  18.           // 十位
  19.           HAL_SPI_Transmit(&hspi2, &data[shi], 1, 1000);
  20.           break;
  21.         case BAI_BIT:
  22.           // 百位
  23.           HAL_SPI_Transmit(&hspi2, &data[bai], 1, 1000);
  24.           break;
  25.         case QIAN_BIT:
  26.           // 千位
  27.           HAL_SPI_Transmit(&hspi2, &data[qian], 1, 1000);
  28.           break;
  29.         default:
  30.           break;
  31.       }
  32.     } // end for

  33.     /* 让锁存输出一个高电平脉冲 */
  34.     HAL_GPIO_WritePin(SPI2_LOAD_GPIO_Port, SPI2_LOAD_Pin, GPIO_PIN_SET);
  35.     HAL_Delay(10);
  36.     HAL_GPIO_WritePin(SPI2_LOAD_GPIO_Port, SPI2_LOAD_Pin, GPIO_PIN_RESET);
  37. } /* end --------- hc74959_display functions ---------------- */
复制代码

main.c 文件中的主循环
  1.   while (1)
  2.   {
  3.   /* USER CODE END WHILE */

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

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

逻辑分析仪的显示情况
spi_led.png

看显示状况是没什么问题。
P71105-220939.jpg


收藏 评论10 发布时间:2017-11-5 22:28

举报

10个回答
liming-367095 回答时间:2017-11-7 09:48:09
支持一下
MrJiu 回答时间:2017-11-7 11:33:01
驱动数码管是啥芯片?
zero99 回答时间:2017-11-20 16:55:54
楼主下次请发求助帖!
七哥 回答时间:2018-3-8 01:29:29
本帖最后由 toofree 于 2018-3-8 01:34 编辑

HAL_SPI_Transmit(&hspi2, &data[shi], 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

评分

参与人数 1蝴蝶豆 +3 收起 理由
zero99 + 3

查看全部评分

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个字节一 ...

知道了,确实是只发送就够了
疯影17 回答时间:2018-4-4 19:53:12
MrJiu 发表于 2017-11-7 11:33
驱动数码管是啥芯片?

74hc595 IMG_20180404_194915.png
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的。
pinganbo 回答时间:2019-12-5 16:41:39
您好,首先程序也是参考了论坛里各位先辈改的。我用的芯片是stm32f410RB,自己画的板子。也是STM32CubeMX配置的,HAL库编写,驱动2片74HC595显示2位数码管。现在的问题是,程序里写的是显示0和1.但实际效果是11.不知道是哪里的问题,把程序填上来。
/*****定义部分******/
uint8_t TX_Data[2]={0xFC,0x60};//想显示0和1
uint8_t data[]={      
       0xFC,/*0*/
       0x60,/*1*/……………….
};
uint16_t num = 0;
/****************/


/******主程序*********/
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_SPI1_Init();
while (1)
  {
   hc74959_display(num);
  }
}
/****************/


/*****595控制部分*****/
void hc74959_display(uint16_t num)
{
   {
     HAL_SPI_MspInit(&hspi1);//使能SPI1
    HAL_SPI_Transmit(&hspi1,TX_Data,2,100);            
  }
   /* 让锁存输出一个高电平脉冲 */
    HAL_GPIO_WritePin(LAT_GPIO_Port, LAT_Pin ,GPIO_PIN_SET);
   HAL_Delay(100);
   HAL_GPIO_WritePin(LAT_GPIO_Port, LAT_Pin , GPIO_PIN_RESET);
    HAL_Delay(100);
    HAL_GPIO_WritePin(LAT_GPIO_Port,LAT_Pin , GPIO_PIN_SET);                       
}
/****************/      

2位LED.jpg
关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版