OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 8422|回复: 8

STM32F4控制步进电机、键盘、数码管、压力传感器、蜂鸣器

[复制链接]

4

主题

23

帖子

0

精华

初级会员

Rank: 2

积分
73
金钱
73
注册时间
2019-5-9
在线时间
21 小时
发表于 2019-9-18 15:41:38 | 显示全部楼层 |阅读模式
最近要做一个新项目,外面写代码又太贵,天天逼着自己学着写,本来基本是小白,硬是花了一个月时间把代码和硬件都做出来了,今天全部程序写完在开发板上调试好了,pcb也发出去打板,给大家分享一下,写的很冗杂,也请大佬们多多指点。

功能是stm32f4控制8个按键,分为两组,每组包括档位键、启动键、暂停键。十个档位,按下档位键时数码管上显示出当前的档位,按下启动键时,键盘锁开启,步进电机1启动,按下暂停键时,步进电机停止。当压力传感器1的压力大于设定值时,电机1自动停止,
切换到电机2运行(运行速度为2号档位键设置的速度),当压力传感器2达到限制时,电机2停止,蜂鸣器报警,说的有点乱,直接上代码了

main.c
#include "sys.h"
#include "delay.h"
#include "pwm.h"
#include "KEY.h"
#include "TM1638.h"
#include "TM1638_2.h"
#include "HX711.h"
#include "HX711B.h"
#include "usart.h"
#include "led.h"
#include "PWM2.h"
#include "BEEP.h"


const unsigned int seg[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};                 //不带小数点           0-9
const unsigned int seg2[10]={0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,0x87,0xff,0xef};         //带小数点                   0.-9.
const unsigned int location[8]={0xc0,0xc2,0xc4,0xc6,0xc8,0xca,0xcc,0xce};          //段码
const unsigned int location2[8]={0xc1,0xc3,0xc5,0xc7,0xc9,0xcb,0xcd,0xcf};
const u8 table_tmp[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};  //显示缓冲区


int main(void)
{
        u8 KEY_NUM=0;        //初始化档位1值
        u8 KEY2_NUM=0;       //初始化档位2值
        u8 KEY_FLAG=0;        //按键标志位
        float Weight = 0;    //初始化压力值
        float Weight2 = 0;    //初始化压力值
       
        KEY_Init();          //初始化与按键连接的硬件端口
        Driver_Init();                         //电机1初始化
        Driver_Init2();      //电机2初始化
        BEEP_Init();                 //初始化蜂鸣器端口
  uart_init(115200);         //串口初始化波特率为115200
        NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2
        delay_init(168);     //初始化延时函数
        display_Init();      //数码管1显示初始化
        display2_Init();      //数码管2显示初始化
        Init_Hx711();        //初始化压力读取
        Get_Maopi();         //去除压力干扰
        Init_Hx711B();        //初始化压力B读取
        Get_MaopiB();         //去除压力B干扰
        delay_ms(1);       
       
                                TM1638_Display(location[0],seg[0]);            //初始数码管1显示状态
                    TM1638_Display(location[1],seg[0]);
                    TM1638_Display(location[2],seg2[0]);
                          TM1638_Display(location[3],seg2[0]);
                                TM1638_Display(location[4],seg2[8]);            
                    TM1638_Display(location[5],seg2[8]);
                    TM1638_Display(location[6],seg2[8]);
                          TM1638_Display(location[7],seg2[8]);
                               
                                TM1638_2_Display(location[0],seg[0]);            //初始数码管2显示状态
                    TM1638_2_Display(location[1],seg[0]);
                    TM1638_2_Display(location[2],seg2[0]);
                          TM1638_2_Display(location[3],seg2[0]);
                                TM1638_2_Display(location[4],seg2[8]);            
                    TM1638_2_Display(location[5],seg2[8]);
                    TM1638_2_Display(location[6],seg2[8]);
                          TM1638_2_Display(location[7],seg2[8]);       
                               
                               
   while(1)
         {
          Weight = Get_Weight();
          Weight = (float)Weight/1000.0f;
          printf("%0.3f \n",Weight);              //串口显示重量
          delay_ms(1);
                  if(Weight>10)
                   {
        TIM3_PWM_Init(1-1 ,84-1);               
        TIM2_PWM_Init (5000/KEY_NUM ,84-1);               
                   }
          Weight2 = Get_WeightB();
          Weight2 = (float)Weight2/1000.0f;
          printf("%0.3f \n",Weight2);              //串口显示重量
          delay_ms(1);
                  if(Weight2>10)
                   {
                                display_Init(); //数码管显示初始化
                     TM1638_Display(location[0],0X80);
                    TM1638_Display(location[1],seg[(KEY_NUM*5)/10]);
                    TM1638_Display(location[2],seg2[(KEY_NUM*5)%10]);
                          TM1638_Display(location[3],seg2[0]);
                          TM1638_Display(location[4],0X39);            //压力显示C
                          TM1638_Display(location[5],0X0f);            //电池显示        .mh/h
                                TM1638_Display(location[6],0X64);            //注射完毕
                                TM1638_Display(location[7],0X0C);            //暂停
        TIM2_PWM_Init(1-1 ,84-1);
        BEEP=1;                                 
                   }                         
                  if(S1==0||P1==0||D1==0||D2==1)
             {
                    delay_ms(10);//去抖动
                     if(D1==0&&KEY_FLAG==0)                 //档位按键
                      {       
                             KEY_NUM++;
                              if(KEY_NUM >=10)
                               {
              KEY_NUM=0;                        
                               }
                              display_Init(); //数码管显示初始化
                              TM1638_Display(location[0],0X80);            //显示小数点
                        TM1638_Display(location[1],seg[(KEY_NUM*5)/10]);
                        TM1638_Display(location[2],seg2[(KEY_NUM*5)%10]);
                              TM1638_Display(location[3],seg2[0]);
                              TM1638_Display(location[4],0X39);            //压力显示C
                              TM1638_Display(location[5],0X0f);            //电池显示.mh/h

                       }
                      else if(S1 ==0&&KEY_FLAG==0)    //启动键
                       {
                              display_Init(); //数码管显示初始化
                              TM1638_Display(location[0],0X80);
                        TM1638_Display(location[1],seg[(KEY_NUM*5)/10]);
                        TM1638_Display(location[2],seg2[(KEY_NUM*5)%10]);
                              TM1638_Display(location[3],seg2[0]);
                                    TM1638_Display(location[4],0X39);            //压力显示C
                              TM1638_Display(location[5],0X0f);            //电池显示.mh/h
                              TM1638_Display(location[7],0X70);            //运行箭头
                              TIM3_PWM_Init(40/KEY_NUM ,84-1);
                                                KEY_FLAG=1;
                       }  
                      else if(P1==0)  //暂停键
                       {
                              display_Init(); //数码管显示初始化
                         TM1638_Display(location[0],0X80);
                        TM1638_Display(location[1],seg[(KEY_NUM*5)/10]);
                        TM1638_Display(location[2],seg2[(KEY_NUM*5)%10]);
                              TM1638_Display(location[3],seg2[0]);
                              TM1638_Display(location[4],0X39);            //压力显示C
                              TM1638_Display(location[5],0X0f);            //电池显示        .mh/h               
                                    TM1638_Display(location[7],0X0C);            //暂停
                              TIM3_PWM_Init(1-1 ,84-1);
            TIM2_PWM_Init(1-1 ,84-1);
            BEEP=0;
            KEY_FLAG =0;                                                 
                       }       
                                         else if(D2==1) //档位2
                                         {
                             KEY2_NUM++;
                              if(KEY2_NUM >=10)
                               {
              KEY2_NUM=0;                        
                               }
                              display2_Init(); //数码管显示初始化
                              TM1638_2_Display(location[0],0X80);            //显示小数点
                        TM1638_2_Display(location[1],seg[(KEY2_NUM*5)/10]);
                        TM1638_2_Display(location[2],seg2[(KEY2_NUM*5)%10]);
                              TM1638_2_Display(location[3],seg2[0]);
                              TM1638_2_Display(location[4],0X39);            //压力显示C
                              TM1638_2_Display(location[5],0X0f);            //电池显示.mh/h
                                         }
               }
       }
}


步进电机

#include "pwm.h"
#include "usart.h"




void Driver_Init(void)
{
        GPIO_InitTypeDef  GPIO_InitStructure;

        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);//使能GPIOC时钟

        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5|GPIO_Pin_4; //ENA使能 DIR方向对应引脚
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;//普通输出模式
        GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100M
        GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
        GPIO_Init(GPIOC, &GPIO_InitStructure);//初始化GPIOA5.4
       
        GPIO_SetBits(GPIOC,GPIO_Pin_4);//PC2输出高 顺时针方向  DIR
        GPIO_ResetBits(GPIOC,GPIO_Pin_5);//PC1输出低 使能输出  ENA
}




//TIM3_CH1 PWM部分初始化
//PWM输出初始化
//arr:自动重装值
//psc:时钟预分频数
void TIM3_PWM_Init(u32 arr,u32 psc)
{                                                          
       
       
        GPIO_InitTypeDef GPIO_InitStructure;
        TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
        TIM_OCInitTypeDef  TIM_OCInitStructure;
       
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);          //TIM3时钟使能   
        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);         //使能PORTA时钟       
       
        GPIO_PinAFConfig(GPIOA,GPIO_PinSource6,GPIO_AF_TIM3); //GPIOA6复用为定时器3
       
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;           //GPIOA6
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;        //复用功能
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;        //速度100MHz
        GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;      //推挽复用输出
        GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;        //上拉
        GPIO_Init(GPIOA,&GPIO_InitStructure);              //初始化PA6
          
        TIM_TimeBaseStructure.TIM_Prescaler=psc;  //定时器分频
        TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; //向上计数模式
        TIM_TimeBaseStructure.TIM_Period=arr;   //自动重装载值
        TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;
       
        TIM_TimeBaseInit(TIM3,&TIM_TimeBaseStructure);//初始化定时器3
       
        //初始化TIM3  Channel1 PWM模式         
        TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //选择定时器模式:TIM脉冲宽度调制模式2
        TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
        TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; //输出极性:TIM输出比较极性低
        TIM_OC1Init(TIM3, &TIM_OCInitStructure);  //根据T指定的参数初始化外设TIM3 OC1

        TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable);  //使能TIM14在CCR1上的预装载寄存器

  TIM_ARRPreloadConfig(TIM3,ENABLE);//ARPE使能
        TIM_SetCompare1 (TIM3,2);             //占空比
       
        TIM_Cmd(TIM3, ENABLE);  //使能TIM3

                                                                                  
}  

数码管


#include"TM1638.h"
#include "stm32f4xx.h"

extern unsigned int seg[10];                 
extern unsigned int seg2[10];                 
extern unsigned int location[8];
extern unsigned int location2[8];
extern  u8 table_tmp[8];

void Delay(vu32 nCount)
{
  for(; nCount != 0; nCount--);
}


/*****************************
        发送函数(不分命令、数据)
*****************************/
void SendDATA1638(unsigned int edata)
{
  unsigned int i=0;
        GPIO_ResetBits(GC,STB);           //STB=0;
        for(i=0;i<8;i++)
        {
          Delay(100);                   //100ns
          GPIO_ResetBits(GC,CLK);          //CLK=0;
          if(edata&0x01)          
          {
             GPIO_SetBits(GC,DIO);          //DIO=1;
                 Delay(200);          //200ns
          }
          else
          {
             GPIO_ResetBits(GC,DIO);        //DIO=0
                 Delay(200);         //200ns
          }
          Delay(100);                         //100ns
          GPIO_SetBits(GC,CLK);                 //CLK=1;
          edata>>=1;
        }
}




/***********************************
  数据显示函数(只适用固定地址模式)
************************************/
void TM1638_Display(unsigned int address,unsigned int number)
{
         GPIO_SetBits(GC,STB);
   SendDATA1638(address);
         Delay(100);           //1μs
         SendDATA1638(number);
         Delay(100);           //1μs
         GPIO_SetBits(GC,STB);
         Delay(100);           //1μs
}




void  display_Init()
{
  int i;
       
        GPIO_InitTypeDef GPIO_InitStructure;

        RCC_AHB1PeriphClockCmd(  RCC_AHB1Periph_GPIOC , ENABLE);
        GPIO_InitStructure.GPIO_Pin = CLK;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
        GPIO_InitStructure.GPIO_OType =GPIO_OType_PP;
        GPIO_Init(GC, &GPIO_InitStructure);

        GPIO_InitStructure.GPIO_Pin = DIO;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(GC, &GPIO_InitStructure);

        GPIO_InitStructure.GPIO_Pin = STB;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
        GPIO_InitStructure.GPIO_OType =GPIO_OType_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(GC, &GPIO_InitStructure);

         GPIO_SetBits(GC,STB);
   SendDATA1638(openLKM);
         GPIO_SetBits(GC,STB);
         Delay(100);
   SendDATA1638(writefix);
         GPIO_SetBits(GC,STB);
       
         for (i=0;i<8;i++)
      {   
      TM1638_Display(location[7-i],table_tmp[i]);
      }     
}

压力传感器


#include "HX711.h"
#include "delay.h"

long HX711_Buffer = 0;
long Weight_Maopi = 0,Weight_Shiwu = 0;

#define GapValue 430
#define HIGH 1
#define LOW  0
#define HX711_GROUP GPIOB


void digitalWrite(GPIO_TypeDef * GPIO,int pin,int value)
{
        if(value==HIGH)//set 1
        {
                GPIO_SetBits(GPIO,pin);
        }
        if(value==LOW)//reset 0
        {
                GPIO_ResetBits(GPIO,pin);
        }
}

int digitalRead(GPIO_TypeDef * GPIO,int pin)
{
        return GPIO_ReadInputDataBit(GPIO,pin);
}

//****************************************************
//初始化HX711
//****************************************************
void Init_Hx711()
{
        GPIO_InitTypeDef  GPIO_InitStructure;

  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);

  //SCK
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 ;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN;
  GPIO_Init(GPIOB, &GPIO_InitStructure);

        GPIO_InitTypeDef  GPIO_InitStructure1;

  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);

  //DOUT
  GPIO_InitStructure1.GPIO_Pin = GPIO_Pin_1 ;
  GPIO_InitStructure1.GPIO_Mode = GPIO_Mode_IN;
  //GPIO_InitStructure1.GPIO_OType = GPIO_OType_OD;
  GPIO_InitStructure1.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure1.GPIO_PuPd = GPIO_PuPd_NOPULL;
  GPIO_Init(GPIOB, &GPIO_InitStructure1);
        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);

}


//****************************************************
//获取毛皮重量
//****************************************************
void Get_Maopi()
{
        Weight_Maopi = HX711_Read();               
}

//****************************************************
//称重
//****************************************************
long Get_Weight()
{
        HX711_Buffer = HX711_Read();
        Weight_Shiwu = HX711_Buffer;
        Weight_Shiwu = Weight_Shiwu - Weight_Maopi;                                //获取实物的AD采样数值。
        Weight_Shiwu = (long)((float)Weight_Shiwu/GapValue);        
        return Weight_Shiwu;
}

//****************************************************
//读取HX711
//****************************************************
unsigned long HX711_Read(void)        //增益128
{
                unsigned long val = 0;
        unsigned char i = 0;

        //判断模块是否准备好
        while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_1));
        delay_us(1);   
        //sck 拉低
        GPIO_ResetBits(GPIOB,GPIO_Pin_0);
        //再次判断是否准备好
        while(!GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_1));

        for(i=0;i<24;i++)
        {
                delay_us(100);
                GPIO_SetBits(GPIOB,GPIO_Pin_0);          
                val=val<<1;
                delay_us(1);  
                GPIO_ResetBits(GPIOB,GPIO_Pin_0);          
                if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_1))  
                val++;
                delay_us(1);
        }
        GPIO_SetBits(GPIOB,GPIO_Pin_0);
        val = val^0x800000;
        delay_us(1);
        GPIO_ResetBits(GPIOB,GPIO_Pin_0);
        delay_us(1);  
        return val;
}






正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

4

主题

23

帖子

0

精华

初级会员

Rank: 2

积分
73
金钱
73
注册时间
2019-5-9
在线时间
21 小时
 楼主| 发表于 2019-9-18 15:46:36 | 显示全部楼层
回复 支持 反对

使用道具 举报

109

主题

5564

帖子

0

精华

资深版主

Rank: 8Rank: 8

积分
10560
金钱
10560
注册时间
2017-2-18
在线时间
1911 小时
发表于 2019-9-18 20:16:18 | 显示全部楼层
多谢分享~~
回复 支持 反对

使用道具 举报

0

主题

4

帖子

0

精华

新手上路

积分
43
金钱
43
注册时间
2019-8-2
在线时间
15 小时
发表于 2019-9-19 16:33:57 | 显示全部楼层
楼主 数码管消隐效果怎么样 会有重影么
回复 支持 反对

使用道具 举报

4

主题

23

帖子

0

精华

初级会员

Rank: 2

积分
73
金钱
73
注册时间
2019-5-9
在线时间
21 小时
 楼主| 发表于 2019-9-19 17:06:43 | 显示全部楼层
一十二 发表于 2019-9-19 16:33
楼主 数码管消隐效果怎么样 会有重影么

切换显示的时候初始化一下数码管,不会有重影,把延时设置的短一点,就不会影响使用效果了,我是这样弄得,不知道还有没有更好的办法
回复 支持 反对

使用道具 举报

0

主题

3

帖子

0

精华

新手入门

积分
19
金钱
19
注册时间
2019-9-27
在线时间
5 小时
发表于 2019-11-5 15:15:18 | 显示全部楼层
楼主,你好强啊,我是个小白,但是做的一个东西跟你的差不多,拉力传感器到一定限值,然后触发一个电机开始转动。不太清楚怎么开始,能不能给点建议呀。感谢感谢
回复 支持 反对

使用道具 举报

4

主题

23

帖子

0

精华

初级会员

Rank: 2

积分
73
金钱
73
注册时间
2019-5-9
在线时间
21 小时
 楼主| 发表于 2019-11-13 09:13:35 | 显示全部楼层
dk32 发表于 2019-11-5 15:15
楼主,你好强啊,我是个小白,但是做的一个东西跟你的差不多,拉力传感器到一定限值,然后触发一个电机开始 ...

我也是个小白,你买一个HX711模块,然后把压力传感器接到模块上,模块跟mcu通信,两根线clk和dio,网上有现成的hx711模块的驱动代码,可以直接用,电机去pwm驱动,压力在程序里设置阀值,超过是就打开pwm
回复 支持 反对

使用道具 举报

0

主题

3

帖子

0

精华

新手入门

积分
19
金钱
19
注册时间
2019-9-27
在线时间
5 小时
发表于 2019-11-27 13:57:29 | 显示全部楼层
大幻想家 发表于 2019-11-13 09:13
我也是个小白,你买一个HX711模块,然后把压力传感器接到模块上,模块跟mcu通信,两根线clk和dio,网上有 ...

好的,感谢,我去试试
回复 支持 反对

使用道具 举报

0

主题

20

帖子

0

精华

初级会员

Rank: 2

积分
193
金钱
193
注册时间
2019-12-13
在线时间
17 小时
发表于 2019-12-18 05:39:41 | 显示全部楼层
多谢分享~~
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-2-24 20:39

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表