打印
[STM32F1]

stm32控制数码管

[复制链接]
962|34
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
chuxh|  楼主 | 2021-3-3 21:32 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
采用stm32控制数码管,采用595和单片机的SPI通信,通信特别不稳定

使用特权

评论回复
沙发
supernan| | 2021-3-3 21:35 | 只看该作者
原理图按看下

使用特权

评论回复
板凳
chenjunt| | 2021-3-3 21:37 | 只看该作者

楼主程序可以公开吗?贴程序看下吧,这么说看不出什么原因

使用特权

评论回复
地板
chuxh|  楼主 | 2021-3-3 21:40 | 只看该作者
#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
}

使用特权

评论回复
5
chuxh|  楼主 | 2021-3-3 21:42 | 只看该作者

使用特权

评论回复
6
wuhany| | 2021-3-3 21:44 | 只看该作者

还有什么现象?能再详细描述下吗?

使用特权

评论回复
7
chuxh|  楼主 | 2021-3-3 21:47 | 只看该作者
数码管乱码,不受控制,其中电路图VDD为5v,为了让数码管更亮,电阻为200欧姆

使用特权

评论回复
8
spark周| | 2021-3-3 21:49 | 只看该作者
先确认595的驱动是否ok

使用特权

评论回复
9
huangchui| | 2021-3-3 21:51 | 只看该作者
再确认595每一路和数码管的对应关系

使用特权

评论回复
10
wyjie| | 2021-3-3 21:53 | 只看该作者
发这么一大堆代码,看不出什么来的。

使用特权

评论回复
11
yszong| | 2021-3-3 21:55 | 只看该作者
和51没什么区别,配置下IO就行了

使用特权

评论回复
12
llljh| | 2021-3-3 21:59 | 只看该作者
你确认如果输出一个固定的后,还会乱闪吗

使用特权

评论回复
13
supernan| | 2021-3-3 22:01 | 只看该作者
我之前用MAX7219玩过。

使用特权

评论回复
14
pangb| | 2021-3-3 22:03 | 只看该作者
你用的是F1哪一个?

使用特权

评论回复
15
xxmmi| | 2021-3-3 22:05 | 只看该作者
如楼上说,你固定一个数值,也乱串?

使用特权

评论回复
16
kangzj| | 2021-3-3 22:07 | 只看该作者
确定驱动IC没问题?

使用特权

评论回复
17
chuxh|  楼主 | 2021-3-3 22:09 | 只看该作者
那不会乱闪了

使用特权

评论回复
18
chuxh|  楼主 | 2021-3-3 22:15 | 只看该作者
F103zet6

使用特权

评论回复
19
spark周| | 2021-3-3 22:17 | 只看该作者
这说明乱闪是你软件没有组织好造成的s

使用特权

评论回复
20
午夜粪车| | 2021-3-3 22:19 | 只看该作者
你显示固定内容没问题,就是切换显示内容的程序没有处理好

使用特权

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

本版积分规则

936

主题

11296

帖子

2

粉丝