在上一个开箱帖中简单介绍了本次活动的开发板和各个模块,在本贴中,将对各个模块进行简单的测试及驱动。
首先是开发板的驱动:当拿到一个开发板的时候,第一个烧录的程序通常是点灯操作。keil的操作相信大家都非常熟悉,本次使用的keil模板是单片机是STM32F103C8T6,我们只需在Device中将单片机型号换成STM32F103RB即可使用。
查阅原理图,发现开发板上共有3个灯,最上面的是st-link指示灯,LD3是电源指示灯,需要我们点亮的是LD2。
在原理图上LD2绿灯与PA5和PB13都进行了连接,那么如何判断它连接的是PA5还是PB13呢?开发板背面有我们需要的答案!
可以看到SB42焊接了0Ω的电阻,而SB29没有。由此可以判断,LD2绿灯与PA5相连。那么下面的操作就非常简单了。
首先是创建.h和.c文件
led.h
#ifndef __LED_H__ #define __LED_H__ #include "stm32f10x.h" #define RCC_GPIO RCC_APB2Periph_GPIOA #define RCC_GPIO_LED RCC_APB2Periph_GPIOA #define LED_GPIO GPIOA #define LED_GPIO_Pin GPIO_Pin_5 void led_init(void); void led_on(void); void led_off(void); #endif
led.c
#include "LED.h" void led_init(void) { GPIO_InitTypeDef GPIOA_Initstruct; RCC_APB2PeriphClockCmd(RCC_GPIO, ENABLE); GPIOA_Initstruct.GPIO_Pin = LED_GPIO_Pin; GPIOA_Initstruct.GPIO_Mode = GPIO_Mode_Out_PP; GPIOA_Initstruct.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(LED_GPIO, &GPIOA_Initstruct); } void led_on(void) { GPIO_SetBits(LED_GPIO, LED_GPIO_Pin); } void led_off(void) { GPIO_ResetBits(LED_GPIO, LED_GPIO_Pin); }
在main.c中添加头文件并初始化,即可点亮LD2。效果如下:
继电器的驱动与LED的驱动类型,都是通过给引脚高低电平开实现功能,只是最终实现的功能不同。继电器的实现效果如下:
给下面的信号线高电平时,继电器模块上的红灯会亮,COM与NO连通。下面是LCD显示模块的驱动,因为LCD模块的显示驱动比较复杂,我们可以将别人写好的模块移植到我我们这块开发板上面。在本次实验中,使用的时软件模拟IIC,所以可以任意选择SDA和SCL,因此选择PC2位SDA,PC3为SCL。使用LCD取模软件获得”瞬间流量“和”累计流量“的数组,将其存入到oledfront.h中。
在main.c中初始化及驱动后,效果如下
最后是比较复杂的流量传感器,它是一种叶轮式水流量传感器,工作原理是当水通过传感器时,会推动叶轮旋转,叶轮上装有磁铁,每旋转一圈时,磁场的变化会被霍尔传感器检测到,霍尔传感器将磁场变化转换为电脉冲信号,脉冲的频率与水流速度成正比。由公式Q=k⋅f即可计算出水流速。在本次实验中,使用中断来接收脉冲信号。
YF_S401.h
#ifndef __YF_S401_H__ #define __YF_S401_H__ #include "sys.h" #include "stdlib.h" #include "stm32f10x.h" //定义流量相关参数 typedef struct { float instant; // 瞬时流量 float acculat; // 累计流量 float cnt; // 脉冲数 } GOLBAL_FLOW; // 定义流量模型的枚举类型 typedef enum { MODE_4_PIPE = 0, // 四分管 MODE_6_PIPE = 1, // 六分管 MODE_6MM_PIPE = 2 // 6mm管 } FlowModel; //引脚定义 #define YF_S401_RCC RCC_APB2Periph_GPIOA #define YF_S401_GPIO GPIOA #define YF_S401_GPIO_PIN GPIO_Pin_1 #define YF_S401_EXTI_Line EXTI_Line1 //函数定义 void bsp_YF_S401_Init(void); void Flow_Read(void); #endif // ! __YF_S401_H__
YF_S401.c
#include "YF_S401.h" GOLBAL_FLOW golbal_flow; // 定义流量参数 float flowK[3] = {5.0f, 5.5f, 40.0f}; // 流量系数 K float pulseCntPerLiter[3] = {300.0f, 330.0f, 4800.0f}; // 每升水脉冲数 // 定义 Flow_Model FlowModel flowModel = MODE_6MM_PIPE; // 默认使用6mm管 u32 pluse1L; // 测试1L水的脉冲数 void bsp_YF_S401_Init(void) { GPIO_InitTypeDef GPIO_InitStruct; EXTI_InitTypeDef EXTI_InitStruct; NVIC_InitTypeDef NVIC_InitStruct; RCC_APB2PeriphClockCmd(YF_S401_RCC, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU; GPIO_InitStruct.GPIO_Pin = YF_S401_GPIO_PIN; GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(YF_S401_GPIO, &GPIO_InitStruct); GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource1); EXTI_InitStruct.EXTI_Line = YF_S401_EXTI_Line; EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt; EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Rising; EXTI_InitStruct.EXTI_LineCmd = ENABLE; EXTI_Init(&EXTI_InitStruct); NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); NVIC_InitStruct.NVIC_IRQChannel = EXTI1_IRQn; NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1; NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1; NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStruct); } /** * @brief 读取YF-S40流量传感器流量 * */ void Flow_Read(void) { // 根据 Flow_Model 选择不同的流量参数 float flowKValue = flowK[flowModel]; float pulseCntValue = pulseCntPerLiter[flowModel]; if (golbal_flow.cnt > 0) { golbal_flow.acculat += (golbal_flow.cnt * 1000 / pulseCntValue); // 单位mL pluse1L += golbal_flow.cnt; golbal_flow.instant = golbal_flow.cnt / flowKValue; // 单位(mL/min) if (golbal_flow.acculat >= 1000000) // 最大累计流量1000L { golbal_flow.acculat = 0; } } else { golbal_flow.instant = 0; } golbal_flow.cnt = 0; } void EXTI1_IRQHandler(void) { if (EXTI_GetITStatus(YF_S401_EXTI_Line) != RESET) { golbal_flow.cnt++; EXTI_ClearITPendingBit(YF_S401_EXTI_Line); } }
在上述代码中,每接收到一个上升沿,程序将产生一次中断,将脉冲数加1,然后再计算瞬间流量和累计流量,并再LCD屏上进行显示实时显示。此外,需要根据水泵的实际情况,对流量参数中的参数进行修改。
本帖是液体流量检测仪活动的过程贴,针对开箱贴中的各个模块进行简单驱动,实际效果并没有达到活动要求,后面将对程序进行调试,以达到实验要求。