做完开箱贴之后,一直没时间继续,这两天回老家之后挤点时间调试一下,总算是把基本功能给实现了。下面讲讲开发的过程:
1、开发环境的选择用Keil, 这个工程还算比较简单,主要问题在霍尔流量传感器的参数不明确,全凭个人调试统计再估计流量,特别是在没有示波器,计量器等的情况下怎么完成目标。
本过程贴说明的是整个软硬件环境搭建与调试。另外一篇过程贴重点讲述霍尔流量传感器的工作及计算原理。
2、功能需求:实现“通过小抽水泵和继电器实现流量控制,结合霍尔效应传感器,实现瞬时流量和累计流量的监测”,几个功能模块:
OLED UI显示;
通过继电器控制抽水泵开关;
检测流量传感器输出的脉冲信号;
2.1 OLED UI显示
采用的是GPIO模拟IIC的方式,PCtoLCD2002添加字模 。
IIC管教选用 PB8,PB9.
//SCL PB8 SDA PB9 #define OLED_SCL_Clr() (GPIO_PinWrite(Pin_OLED[0].port, Pin_OLED[0].num, 0)) #define OLED_SCL_Set() (GPIO_PinWrite(Pin_OLED[0].port, Pin_OLED[0].num, 1)) #define OLED_SDA_Clr() (GPIO_PinWrite(Pin_OLED[1].port, Pin_OLED[1].num, 0)) #define OLED_SDA_Set() (GPIO_PinWrite(Pin_OLED[1].port, Pin_OLED[1].num, 1)) const GPIO_PIN_ID Pin_OLED[] = { { GPIOB, 8 }, { GPIOB, 9 } }; int32_t OLED_Initialize (void) { uint32_t n; /* Configure pins: Push-pull Output Mode (50 MHz) with Pull-down resistors */ for (n = 0; n < OLED_PINCOUNT; n++) { GPIO_PortClock (Pin_OLED[n].port, true); GPIO_PinWrite (Pin_OLED[n].port, Pin_OLED[n].num, 1); GPIO_PinConfigure(Pin_OLED[n].port, Pin_OLED[n].num, GPIO_OUT_PUSH_PULL, GPIO_MODE_OUT50MHZ); } }
字体尽量简化,少用几个汉字。
const unsigned char Chinese_16x16[][32]= { //液(0) 泵(1) 流(2) 速(3) 量(4) 监(5) 测(6) 仪(7)定(8) {0x10,0x60,0x02,0x8C,0x00,0x84,0xE4,0x1C,0x05,0xC6,0xBC,0x24,0x24,0xE4,0x04,0x00,0x04,0x04,0x7E,0x01,0x00,0x00,0xFF,0x82,0x41,0x26,0x18,0x29,0x46,0x81,0x80,0x00},/*"液",0*/ {0x42,0x42,0x22,0x12,0xFA,0x96,0x92,0x92,0x92,0x92,0x92,0xF2,0x02,0x02,0x02,0x00,0x40,0x44,0x24,0x14,0x0C,0x44,0x80,0x7F,0x04,0x08,0x10,0x28,0x24,0x42,0x40,0x00},/*"泵",1*/ {0x10,0x60,0x02,0x8C,0x00,0x44,0x64,0x54,0x4D,0x46,0x44,0x54,0x64,0xC4,0x04,0x00,0x04,0x04,0x7E,0x01,0x80,0x40,0x3E,0x00,0x00,0xFE,0x00,0x00,0x7E,0x80,0xE0,0x00},/*"流",2*/ {0x40,0x40,0x42,0xCC,0x00,0x04,0xF4,0x94,0x94,0xFF,0x94,0x94,0xF4,0x04,0x00,0x00,0x00,0x40,0x20,0x1F,0x20,0x48,0x44,0x42,0x41,0x5F,0x41,0x42,0x44,0x48,0x40,0x00},/*"速",3*/ {0x20,0x20,0x20,0xBE,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xBE,0x20,0x20,0x20,0x00,0x00,0x80,0x80,0xAF,0xAA,0xAA,0xAA,0xFF,0xAA,0xAA,0xAA,0xAF,0x80,0x80,0x00,0x00},/*"量",4*/ {0x00,0x00,0x7E,0x00,0x00,0xFF,0x00,0x40,0x30,0x0F,0x04,0x14,0x64,0x04,0x00,0x00,0x40,0x40,0x7E,0x42,0x42,0x7E,0x42,0x42,0x42,0x7E,0x42,0x42,0x7E,0x40,0x40,0x00},/*"监",5*/ {0x10,0x60,0x02,0x8C,0x00,0xFE,0x02,0xF2,0x02,0xFE,0x00,0xF8,0x00,0xFF,0x00,0x00,0x04,0x04,0x7E,0x01,0x80,0x47,0x30,0x0F,0x10,0x27,0x00,0x47,0x80,0x7F,0x00,0x00},/*"测",6*/ {0x00,0x80,0x60,0xF8,0x07,0x00,0x1C,0xE0,0x01,0x06,0x00,0xE0,0x1E,0x00,0x00,0x00,0x01,0x00,0x00,0xFF,0x00,0x80,0x40,0x20,0x13,0x0C,0x13,0x20,0x40,0x80,0x80,0x00},/*"仪",7*/ {0x10,0x0C,0x44,0x44,0x44,0x44,0x45,0xC6,0x44,0x44,0x44,0x44,0x44,0x14,0x0C,0x00,0x80,0x40,0x20,0x1E,0x20,0x40,0x40,0x7F,0x44,0x44,0x44,0x44,0x44,0x40,0x40,0x00},/*"定",8*/ };
注意:这个程序并没有经过严格的测试,只是初步实现了定量给水的功能,如需提高精度,需要示波器,计量器等进行标定。如有错漏请不吝指出
2.2 通过继电器控制抽水泵开关
继电器的使用说明,继电器在不通电或者没导通情况下COM端默认打到NC即相通,继电器开关导通后COM和NO打通,COM和NC断开。
规格书:
类型:数字
单继电器板
额定直流:10A(NO) 5A(NC)
最大开关电压:150VAC 24VDC
数字接口
控制信号:TTL电平额定负载: 8A150VAC(无) 10A24VDC(无),5A250VAC(无/无) 5A24VDC(无/无)
最大开关功率: AC1200VA DC240W(无) AC625VA DC120W(无)
最快动作时间:10毫秒模块(继电器的控制周期设置大于10ms,否则影响继电器动作,从而影响判断)
由于继电器和水泵的的功率比较大,所以尽量直接用电源模块供电,不要从开发板取电。
引脚定义:引脚1D-控制端(PA8),引脚2-电源(5V),引脚3-接地
接线端子:COM-电源(5V) ,COM-水泵正极,水泵负极 接地
int32_t Relay_Initialize (void) { GPIO_PortClock (GPIOA, true); GPIO_PinWrite (GPIOA, 8, 0); GPIO_PinConfigure(GPIOA, 8, GPIO_OUT_PUSH_PULL, GPIO_MODE_OUT50MHZ); // while(1) //调试用 // { // // GPIO_PinWrite (GPIOA, 8, 1); // delay_ms(1000); // Wait 1000ms // // GPIO_PinWrite (GPIOA, 8, 0); // // delay_ms(1000); // Wait 1000ms // // } return (0); }
置高PA8管脚电平,可通过万用表测量 NO与COM是否接通。
2.3 检测流量传感器输出的脉冲信号
选择PD2作为外部中断引脚检测流量传感器的输出脉冲信号,上升沿触发中断函数,添加一个变量作为脉冲计数。
void EXITX_Tnit(GPIO_TypeDef* GPIOX,uint16_t PIN) { /*开启时钟*/ RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); //开启AFIO时钟 /*GPIO初始化*/ if(GPIOX == GPIOA) gpio_init(RCC_APB2Periph_GPIOA,GPIO_Mode_IPU,GPIOA,PIN); if(GPIOX == GPIOB) gpio_init(RCC_APB2Periph_GPIOB,GPIO_Mode_IPU,GPIOB,PIN); if(GPIOX == GPIOC) gpio_init(RCC_APB2Periph_GPIOC,GPIO_Mode_IPU,GPIOC,PIN); if(GPIOX == GPIOD) gpio_init(RCC_APB2Periph_GPIOD,GPIO_Mode_IPU,GPIOD,PIN); if(GPIOX == GPIOA) GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GetPinSource(PIN));//将外部中断的N号线映射到GPIO if(GPIOX == GPIOB) GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GetPinSource(PIN)); if(GPIOX == GPIOC) GPIO_EXTILineConfig(GPIO_PortSourceGPIOC, GetPinSource(PIN)); if(GPIOX == GPIOD) GPIO_EXTILineConfig(GPIO_PortSourceGPIOD, GetPinSource(PIN)); /*EXTI初始化*/ EXTI_InitTypeDef EXTI_InitStructure; //定义结构体变量 EXTI_InitStructure.EXTI_Line = (uint32_t)PIN; //选择配置外部中断的14号线 EXTI_InitStructure.EXTI_LineCmd = ENABLE; //指定外部中断线使能 EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; //指定外部中断线为中断模式 EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising; //指定外部中断线为下降沿触发 EXTI_Init(&EXTI_InitStructure); //将结构体变量交给EXTI_Init,配置EXTI外设 /*NVIC配置*/ NVIC_InitTypeDef NVIC_InitStructure; //定义结构体变量 if(PIN == 0x0001) NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn; //选择配置NVIC的EXTI0线 if(PIN == 0x0002) NVIC_InitStructure.NVIC_IRQChannel = EXTI1_IRQn; //选择配置NVIC的EXTI1线 if(PIN == 0x0004) NVIC_InitStructure.NVIC_IRQChannel = EXTI2_IRQn; //选择配置NVIC的EXTI2线 if(PIN == 0x0008) NVIC_InitStructure.NVIC_IRQChannel = EXTI3_IRQn; //选择配置NVIC的EXTI3线 if(PIN == 0x0010) NVIC_InitStructure.NVIC_IRQChannel = EXTI4_IRQn; //选择配置NVIC的EXTI4线 if((PIN & 0x03E0) != 0x0000) NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn; //选择配置NVIC的EXTI9_5线 if((PIN & 0xFC00) != 0x0000) NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn; //选择配置NVIC的EXTI15_10线 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //指定NVIC线路使能 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; //指定NVIC线路的抢占优先级为1 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; //指定NVIC线路的响应优先级为1 NVIC_Init(&NVIC_InitStructure); //将结构体变量交给NVIC_Init,配置NVIC外设 } // 初始化 EXITX_Tnit(GPIOD,GPIO_Pin_2);
关于流量传感器的检测具体看 Let'sDo第4期【液体流量检测仪】 过程贴:霍尔水流量传感器的工作原理