最近要做一个新项目,外面写代码又太贵,天天逼着自己学着写,本来基本是小白,硬是花了一个月时间把代码和硬件都做出来了,今天全部程序写完在开发板上调试好了,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
",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
",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);
}
}
压力传感器
#include &quot;HX711.h&quot;
#include &quot;delay.h&quot;
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;
} |