打印
[STM32F1]

stm32控制数码管

[复制链接]
6186|19
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
采用stm32控制数码管,采用595和单片机的SPI通信,通信特别不稳定,原理图如下,代码
如下
#include "stm32f10x_lib.h"          //包含了所有的头文件 它是唯一一个用户需要包括在自己应用中的文件,起到应用和库之间界面的作用。

#define        HC595_nCS                 GPIO_Pin_0                        //HC595_nCS = PA0
#define        HC595_RCK                 GPIO_Pin_1                        //HC595_RCK = PA1

#define        SEG_A1                         GPIO_Pin_8                        //SEG_A1 = PC8
#define        SEG_A2                         GPIO_Pin_15                        //SEG_A2 = PB15
#define        SEG_A3                         GPIO_Pin_9                        //SEG_A3 = PC9
#define        SEG_A4                         GPIO_Pin_8                        //SEG_A4 = PE8

u8 const NumberTube_TAB[10]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90};//数码管0~9
/*******************************************************************************
* Function Name  : SEG_Init
* Description    : SEG数码管引脚,SPI1引脚初始化
* Input          : None
* Return         : None
*******************************************************************************/
void        SEG_Init(void)
{
        GPIO_InitTypeDef GPIO_InitStructure;        // 声明一个IO口结构体变量
        SPI_InitTypeDef SPI1_InitStructure;        //声明一个SPI结构体变量

        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA , ENABLE);        // 使能APB2外设GPIOA时钟
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB , ENABLE);        // 使能APB2外设GPIOB时钟
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC , ENABLE);        // 使能APB2外设GPIOC时钟
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE , ENABLE);        // 使能APB2外设GPIOE时钟
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1 , ENABLE);        // 使能APB2外设SPI1时钟
       
    //==========PA口IO结构体初始化============
          GPIO_InitStructure.GPIO_Pin        = HC595_nCS|HC595_RCK;        //选择PA.0,PA.1
          GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;        //管脚频率为50MHZ
          GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;        //模式为推挽输出
          GPIO_Init(GPIOA, &GPIO_InitStructure);                           //初始化GPIOA寄存器
        //==========PB口IO结构体初始化============
          GPIO_InitStructure.GPIO_Pin        = SEG_A2;        //选择PB.15
          GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;        //管脚频率为50MHZ
          GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;        //模式为推挽输出
          GPIO_Init(GPIOB, &GPIO_InitStructure);                           //初始化GPIOB寄存器
        //==========PC口IO结构体初始化============
          GPIO_InitStructure.GPIO_Pin        = SEG_A1|SEG_A3;                //选择PC.8,PC.9
          GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;        //管脚频率为50MHZ
          GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;        //模式为推挽输出
          GPIO_Init(GPIOC, &GPIO_InitStructure);                           //初始化GPIOC寄存器
        //==========PE口IO结构体初始化============
          GPIO_InitStructure.GPIO_Pin        = SEG_A4;                                //选择PE.8
          GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;        //管脚频率为50MHZ
          GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;        //模式为推挽输出
          GPIO_Init(GPIOE, &GPIO_InitStructure);                           //初始化GPIOE寄存器

        //==========SPI1复用功能初始化============
        GPIO_InitStructure.GPIO_Pin        = GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7;        //选择PA.4,PA.5, PA.6,PA.7
          GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;        //管脚频率为50MHZ
          GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;        //模式为复用推挽输出 (SPI1)
          GPIO_Init(GPIOA, &GPIO_InitStructure);                           //初始化GPIOA寄存器

        //==========设置SPI1工作模式==============
        SPI1_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;        //SPI设置为双线双向全双工
        SPI1_InitStructure.SPI_Mode = SPI_Mode_Master;                                        //设置为主SPI
        SPI1_InitStructure.SPI_DataSize = SPI_DataSize_8b;                                //SPI发送接收8位帧结构
        SPI1_InitStructure.SPI_CPOL = SPI_CPOL_High;                                        //CPOL = 1
        SPI1_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;                                        //CPHA = 0
        SPI1_InitStructure.SPI_NSS = SPI_NSS_Hard;                                                //NSS由外部管脚管理
        SPI1_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_64;//分频值为64
        SPI1_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;                                        //数据传输LSB(低位)开始
        SPI1_InitStructure.SPI_CRCPolynomial = 7;                                               
        SPI_I2S_DeInit(SPI1);        //将外设SPI1寄存器重设为缺省值 ;
        SPI_Init(SPI1, &SPI1_InitStructure);//初始化外设SPI1寄存器
       
        //==========使能SPI1========================
        SPI_Cmd(SPI1, ENABLE);//使能SPI1外设
        GPIO_ResetBits(GPIOA, HC595_nCS);
}                                                                               
/*******************************************************************************
* Function Name  : SEG_BitSelect
* Description    : 选择数码管的位选
* Input          : data        选择码        ,data的取值为0x01,0x02,0x04,0x08
* Return         : None
*******************************************************************************/
void SEG_BitSelect(u8 data)
{
        if((data & 0x01) != 0)        GPIO_ResetBits(GPIOC, SEG_A1);        // 控制smgA1 = PC8
        else                GPIO_SetBits(GPIOC, SEG_A1);
        if((data & 0x02) != 0)        GPIO_ResetBits(GPIOB, SEG_A2);        // 控制smgA2 = PB15
        else                GPIO_SetBits(GPIOB, SEG_A2);
        if((data & 0x04) != 0)        GPIO_ResetBits(GPIOC, SEG_A3);        // 控制smgA3 = PC9
        else                GPIO_SetBits(GPIOC, SEG_A3);
        if((data & 0x08) != 0)        GPIO_ResetBits(GPIOE, SEG_A4);        // 控制smgA4 = PE8
        else                GPIO_SetBits(GPIOE, SEG_A4);
}       
/*******************************************************************************
* Function Name  : SEG_Display
* Description    : 数码管显示4位数据
* Input          : data                需要显示的数据
*                        radix_point        小数点的位置,取值范围为4、3、2
* Return         : None
*******************************************************************************/
void        SEG_Display(u16 data,u8 radix_point)
{
        u16 j,one,ten,hundred,thousand;                //个,十,百,千,的变量声明
       
        thousand = data / 1000;                                        //计算千位
        if(thousand != 0)   data -= thousand*1000;
        hundred = data / 100;                                        //计算百位
        if(hundred != 0) data -= hundred*100;        
        ten = data / 10;                                        //计算十位
        if(ten != 0) data -= ten*10;                
        one = data % 10;                                        //计算个位
        //-------------------显示千位数据----------------
        GPIO_ResetBits(GPIOA, HC595_RCK);
        if(radix_point==4)                SPI_I2S_SendData(SPI1, NumberTube_TAB[thousand] & 0x7f);
        else                        SPI_I2S_SendData(SPI1, NumberTube_TAB[thousand] );
        GPIO_SetBits(GPIOA, HC595_RCK);
        SEG_BitSelect(0x08);        //打开数码管位选端
        for(j=0;j<500;j++);        //小段延时
        SEG_BitSelect(0x00);        //关闭显示
        //-------------------显示百位数据----------------
        GPIO_ResetBits(GPIOA, HC595_RCK);
        if(radix_point==3)                SPI_I2S_SendData(SPI1, NumberTube_TAB[hundred] & 0x7f);
        else                        SPI_I2S_SendData(SPI1, NumberTube_TAB[hundred] );
        GPIO_SetBits(GPIOA, HC595_RCK);
        SEG_BitSelect(0x01);               
        for(j=0;j<500;j++);       
        SEG_BitSelect(0x00);        //关闭显示
        //-------------------显示十位数据----------------
        GPIO_ResetBits(GPIOA, HC595_RCK);
        if(radix_point==2)                SPI_I2S_SendData(SPI1, NumberTube_TAB[ten] & 0x7f);
        else                        SPI_I2S_SendData(SPI1, NumberTube_TAB[ten] );
        GPIO_SetBits(GPIOA, HC595_RCK);
        SEG_BitSelect(0x02);
        for(j=0;j<500;j++);       
        SEG_BitSelect(0x00);        //关闭显示       
        //-------------------显示个位数据----------------
        GPIO_ResetBits(GPIOA, HC595_RCK);
        SPI_I2S_SendData(SPI1, NumberTube_TAB[one] );
        GPIO_SetBits(GPIOA, HC595_RCK);
        SEG_BitSelect(0x04);
        for(j=0;j<500;j++);
        SEG_BitSelect(0x00);        //关闭显示
}       
/*******************************************************************************
* Function Name  : SEG_POWEROFF
* Description    : SEG数码管关闭
* Input          : None
* Return         : None
*******************************************************************************/
void        SEG_POWEROFF(void)
{
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1 , DISABLE);        // 关闭APB2外设SPI1时钟
        GPIO_SetBits(GPIOC, SEG_A1);
        GPIO_SetBits(GPIOB, SEG_A2);
        GPIO_SetBits(GPIOC, SEG_A3);
        GPIO_SetBits(GPIOE, SEG_A4);
}
然后main.c文件如下:int main()
{
//        u16 i=0,j;
        #ifdef DEBUG
          debug();
        #endif

          //RCC_Configuration();//使能外设时钟
        SEG_Init();

        //========实现数码管显示==========
          while (1)
          {
//                for(i=1;i<9;i++)
//                {
//                        for(j=0;j<500;j++)
//                                SEG_Display(i,3);
//                }                  
                SEG_Display(1234,2);
                Delay_Ms(2000);         Delay_Ms(2000);Delay_Ms(2000);
          }       
}


/*******************************************************************************
* Function Name  : Delay_Ms
* Description    : delay 1 ms.
* Input          : time (ms)
* Output         : None
* Return         : None
*******************************************************************************/
void Delay_Ms(u16 time)  //延时函数
{
        u16 i,j;
        for(i=0;i<time;i++)
                  for(j=1000;j>0;j--);
}

/*******************************************************************************
* Function Name  : RCC_Configuration
* Description    : Configures the different system clocks.
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void RCC_Configuration(void)
{
        //==========================使用外部RC晶振========================================
          RCC_DeInit();                                //初始化为缺省状态
          RCC_HSEConfig(RCC_HSE_ON);  //高速时钟使能
          while (RCC_GetFlagStatus(RCC_FLAG_HSERDY) == RESET);  //等待高速时钟使能就绪

    FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);        //Enable Prefetch Buffer
    FLASH_SetLatency(FLASH_Latency_2);                                                  // Flash 2 wait state
    RCC_HCLKConfig(RCC_SYSCLK_Div1);                                                 // HCLK = SYSCLK
    RCC_PCLK2Config(RCC_HCLK_Div1);                                                        // PCLK2 = HCLK
    RCC_PCLK1Config(RCC_HCLK_Div2);                                                          // PCLK1 = HCLK/2
    RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);        // PLLCLK = 8MHz * 9 = 72 MHz  
    RCC_PLLCmd(ENABLE);                                                                                  // Enable PLL
    while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);                // Wait till PLL is ready

    RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);                                  // Select PLL as system clock source
    while(RCC_GetSYSCLKSource() != 0x08);                                        // Wait till PLL is used as system clock source
}

CAO(`M]045@_JB39U)FQUVP.png (117.53 KB )

CAO(`M]045@_JB39U)FQUVP.png
沙发
babyrabbit|  楼主 | 2018-3-19 21:09 | 只看该作者

RE: stm32控制数码管

本帖最后由 babyrabbit 于 2018-3-19 21:12 编辑

数码管乱码,不受控制,其中电路图VDD为5v,为了让数码管更亮,电阻为200欧姆

使用特权

评论回复
板凳
xyz549040622| | 2018-3-19 21:30 | 只看该作者
本帖最后由 xyz549040622 于 2018-3-19 21:31 编辑

1.先确认595的驱动是否ok
2.再确认595每一路和数码管的对应关系
发这么一大堆代码,看不出什么来的。

使用特权

评论回复
地板
一路向北lm| | 2018-3-19 21:43 | 只看该作者
和51没什么区别,配置下IO就行了

使用特权

评论回复
5
antusheng| | 2018-3-20 11:21 | 只看该作者
你确认如果输出一个固定的后,还会乱闪吗

使用特权

评论回复
6
antusheng| | 2018-3-20 11:22 | 只看该作者
我之前用MAX7219玩过。

使用特权

评论回复
7
蝴蝶泉2018| | 2018-3-20 12:11 | 只看该作者
你用的是F1哪一个?如楼上说,你固定一个数值,也乱串?确定驱动IC没问题?

使用特权

评论回复
8
babyrabbit|  楼主 | 2018-3-20 12:20 | 只看该作者
antusheng 发表于 2018-3-20 11:21
你确认如果输出一个固定的后,还会乱闪吗

那不会乱闪了

使用特权

评论回复
9
babyrabbit|  楼主 | 2018-3-20 12:21 | 只看该作者
蝴蝶泉2018 发表于 2018-3-20 12:11
你用的是F1哪一个?如楼上说,你固定一个数值,也乱串?确定驱动IC没问题?

F103zet6

使用特权

评论回复
10
antusheng| | 2018-3-20 12:24 | 只看该作者

这说明乱闪是你软件没有组织好造成的s

使用特权

评论回复
11
antusheng| | 2018-3-20 12:26 | 只看该作者
你显示固定内容没问题,就是切换显示内容的程序没有处理好,比如切换太频繁,看起来就乱闪了

使用特权

评论回复
12
babyrabbit|  楼主 | 2018-3-20 12:28 | 只看该作者
本帖最后由 babyrabbit 于 2018-3-20 12:32 编辑
antusheng 发表于 2018-3-20 12:26
你显示固定内容没问题,就是切换显示内容的程序没有处理好,比如切换太频繁,看起来就乱闪了 ...

好的 在检查一下程序问题  感谢

使用特权

评论回复
13
619888476| | 2018-3-20 15:19 | 只看该作者
先单独调试每路的显示是否正确

使用特权

评论回复
14
LianBinbing| | 2018-3-20 15:27 | 只看该作者
表示没用过!

使用特权

评论回复
15
xujihu| | 2018-3-20 22:10 | 只看该作者
信号线上加几个331的电容,

使用特权

评论回复
16
huajiata| | 2018-3-22 10:25 | 只看该作者
看看时间切换的是不是太快

使用特权

评论回复
17
734774645| | 2018-3-22 23:01 | 只看该作者
调试出来毛病了吗

使用特权

评论回复
18
Bjorn| | 2018-3-23 19:35 | 只看该作者
确定驱动IC没问题?

使用特权

评论回复
19
linda_6000| | 2019-5-5 09:48 | 只看该作者
楼主后来怎么样了?也正在搞这款

使用特权

评论回复
20
单片小菜| | 2019-5-5 09:59 | 只看该作者
时序的问题,调整一下时序

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

23

主题

88

帖子

3

粉丝