本节主要展示上位机部分,采用BSP编程,不附带BSP中各个头文件的说明,仅仅是对main逻辑进行解释
main.c
上下位机通信
通过串口通信,有两位数据验证头(verify数组中保存对应的数据头 0xAA55)
通信格式
上位发送11字节数据,其中前两位是0xAA55用于数据验证,第三位用于判断当前上位机发送数据的功能
当第三位数据为0x00时,表明当前是验证数据,用于检验串口通信是否成功,若成功返回字节序列 [0xaa ,0x55,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09]
当第三位数据为0x01时,表明当前是收集温度,光照,土壤湿度数据,返回字节序列 [0xaa ,0x55,0x01,0x温度十位,0x温度个位,0x温度小数位,0x光照百位,0x光照十位,0x光照个位,0x,0x电压个位,0x电压小数位]
当第三位数据为0x02时,表明当前是修改温度,光照,土壤湿度阈值
在函数my1S中定义了收集温度,光照,土壤湿度数据的实现函数,并且通过检验数据是否超过阈值来触发蜂鸣器报警,根据不同的触发条件来发出不同的声音。
全部代码
cpp
#include "STC15F2K60S2.H" //±ØÐë¡£
#include "sys.H" //±ØÐë¡£
#include "Uart1.H"
#include "adc.h"
#include "displayer.H"
#include "Beep.H"
#include "StepMotor.h"
#define N 11
#ifdef _displayer_H_
code char decode_table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x00,0x08,0x40,0x01, 0x41, 0x48,
/* ÐòºÅ: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 */
/* ÏÔʾ: 0 1 2 3 4 5 6 7 8 9 (ÎÞ) ÏÂ- ÖÐ- ÉÏ- ÉÏÖÐ- ÖÐÏÂ- */
0x3f|0x80,0x06|0x80,0x5b|0x80,0x4f|0x80,0x66|0x80,0x6d|0x80,0x7d|0x80,0x07|0x80,0x7f|0x80,0x6f|0x80 };
/* ´øСÊýµã 0 1 2 3 4 5 6 7 8 9 */
#endif
code unsigned long SysClock=11059200; //±ØÐë¡£¶¨Òåϵͳ¹¤×÷ʱÖÓƵÂÊ(Hz)£¬ÓÃ>>§±ØÐëÐ޸ijÉÓëʵ¼Ê¹¤×÷ƵÂÊ£¨ÏÂÔØʱѡÔñµÄ£©Ò>>ÖÂ
unsigned char rxdbuf[N],txdbuf[N];
code char verify[2]={0xaa,0x55};
unsigned int s0,s1,s2,s3,s4,s5,s6,s7;
unsigned char limit[8] = {3,7,5,0,9,0,1,0};
int rt_to_tem(unsigned int adc, unsigned char adcbit)
{ code int temtable[32]={2000,1293,1016,866,763,685,621,567,520,477,439,403,370,338,308,278,250,222,194,167,139,111,83,53,22,-11,-4.7,-87,-132,-186,-256,-364};
unsigned char resh; //¸ß5bit ²é±í
unsigned int resl; //µÍ11bit ²åÖµ
resl=adc<<(16-adcbit); //ÏÈͳÒ>>À©Õ¹³É16bit
resh=resl>>11;
resl=resl & 0x07ff;
return(temtable[resh]-(((temtable[resh]-temtable[resh+1])*resl)>>11));
}
void check_received_data(void) {
unsigned int flag = 0;
unsigned int data_flag = 0;
unsigned int change_flag = 0;
if(rxdbuf[2] == 0x00) flag = 1;
if(rxdbuf[2] == 0x01) data_flag = 1;
if(rxdbuf[2] == 0x02) change_flag = 1;
if(flag){
txdbuf[0] = 0xaa;
txdbuf[1] = 0x55;
txdbuf[2] = 0x00;
txdbuf[3] = 0x01;
txdbuf[4] = 0x02;
txdbuf[5] = 0x03;
txdbuf[6] = 0x04;
txdbuf[7] = 0x05;
txdbuf[8] = 0x06;
txdbuf[9] = 0x07;
txdbuf[10] = 0x08;
Uart1Print(txdbuf, sizeof(txdbuf));
}if(!flag && data_flag){//
txdbuf[0] = 0xaa;
txdbuf[1] = 0x55;
txdbuf[2] = 0x01;
txdbuf[3] = s0;
txdbuf[4] = s1;
txdbuf[5] = s2;
txdbuf[6] = s3;
txdbuf[7] = s4;
txdbuf[8] = s5;
txdbuf[9] = s6;
txdbuf[10] = s7;
Uart1Print(txdbuf, sizeof(txdbuf));
}if(!flag && change_flag){
limit[0] = rxdbuf[3];
limit[1] = rxdbuf[4];
limit[2] = rxdbuf[5];
limit[3] = rxdbuf[6];
limit[4] = rxdbuf[7];
limit[5] = rxdbuf[8];
limit[6] = rxdbuf[9];
limit[7] = rxdbuf[10];
txdbuf[0] = 0xaa;
txdbuf[1] = 0x55;
txdbuf[2] = 0x02;
txdbuf[3] = limit[0];
txdbuf[4] = limit[1];
txdbuf[5] = limit[2];
txdbuf[6] = limit[3];
txdbuf[7] = limit[4];
txdbuf[8] = limit[5];
txdbuf[9] = limit[6];
txdbuf[10] = limit[7];
Uart1Print(txdbuf, sizeof(txdbuf));
}
}
void my1S()
{
static unsigned int temperature_sum=0;
static unsigned int light_sum = 0;
static unsigned int voltage_ge_sum = 0;
static unsigned int voltage_xiaoshu_sum = 0;
static unsigned int count=0;
int temperature_tem;
int light_tem;
int voltage_ge_tem;
int voltage_xiaoshu_tem;
struct_ADC adcres;
int temperature_shi;
int temperature_ge;
int temperature_xiaoshu;
int temperature;
int temperature_aac;
int light_bai;
int light_shi;
int light_ge;
int voltage_ge;
int voltage_xiaoshu;
int voltage;
int i=0;
adcres=GetADC();
temperature_sum = adcres.Rt;
temperature_tem = rt_to_tem(temperature_sum,14);
temperature_shi = temperature_tem/100%10;
temperature_ge = temperature_tem/10%10;
temperature_xiaoshu = temperature_tem%10;
temperature = temperature_shi *100 + temperature_ge * 10 + temperature_xiaoshu - 320;
temperature_shi = (temperature * 10 / 18) /100;
temperature_ge = (temperature * 10 /18) %100 /10;
temperature_xiaoshu = (temperature * 10 /18) %10;
s0 = temperature_shi;
s1 = temperature_ge-2;
s2 = temperature_xiaoshu;
temperature_aac=s0*10+s1*1+s2*0.1;
light_sum = adcres.Rop;
light_tem = light_sum;
light_bai = light_tem%1000/100;
light_shi = light_tem%100/10;
light_ge = light_tem%10;
s3 = light_bai;
s4 = light_shi;
s5 = light_ge;
voltage_ge_sum = adcres.EXT_P10/50;
voltage_xiaoshu_sum = adcres.EXT_P10%50/5;
voltage_ge = voltage_ge_sum;
voltage_xiaoshu = voltage_xiaoshu_sum;
voltage = (adcres.EXT_P10%1000/100) * 100 + (adcres.EXT_P10%100/10) * 10 + adcres.EXT_P10%10;
s6 = voltage / 50;
s7 = voltage%50/5;
if(light_sum>90)
{SetBeep(1000,200);}
if(temperature_aac>38)
{SetBeep(8000,50);}
if(s6>=3)
{SetBeep(2000,100);
P41 &=~ 0X2;
}
if(s6<3)
{
for( i=0;i<60;i++)
{
P41 |= 0X2;
}
}
Seg7Print(s0,16+s1,s2,s3,s4,s5,16+s6,s7); //ÿ160mSÏÔʾÒ>>´Îζȣ¬Ã¿´ÎÊÇ16´Î²âÁ¿µÄƽ¾ù tem%10
}
void main()
{
Uart1Init(9600);
AdcInit(ADCexpEXT);
DisplayerInit();
BeepInit();
StepMotorInit();
SetDisplayerArea(0,7);
LedPrint(0);
P41 |= 0X2;
SetUart1Rxd(rxdbuf, sizeof(rxdbuf), verify, 2);
SetEventCallBack(enumEventSys1S,my1S);
SetEventCallBack(enumEventUart1Rxd, check_received_data);
MySTC_Init();
while(1)
{
MySTC_OS();
}
}
硬件电路连接
扩展了树莓派的自动灌溉模块,链接如下:灌溉元件
元件单独使用的链接图,但是由于我们需要获取实时电压,我们选择将 AO 接入到 P1.0 来做数模转换,与之对应的是对于继电器的 IN 端口,我们采用stc-b板的vcc来给它供电,这是因为电池提供的电压是6v,超过了继电器的 5v 需求,电源只用来给水泵供电。
整体线路图
外加电源
黄色的模块竖串联,横断路
检测单元
驱动模块