原创 【博客大赛】手把手教你写电子打奶器软件程序(三)-温度转换处理模块

2016-4-27 16:17 1509 20 20 分类: MCU/ 嵌入式

一、温度处理模块程序:

我们采用模块化编程风格,有利于管理项目工程,也更容易查找BUG,大家千万要形成一个好的代码风格,不要一个main.c文件从头写到尾,各种函数都在main.c里面,这样让人看起来烟花缭乱,程序出现BUG也不利于分析问题。因此,最好是每个模块建立一个.c文件和一个.h文件,这样其他模块通过调用该模块的头文件即可。建议大家有空多看看代码风格方面的帖子,会对大家有个好的帮助的。好了,废话不多说,进入正题吧。

1、首先,我们建立一个temperature.h和一个temperature.c文件,将temperature.c文件添加到项目keil工程,并且在temperature.c文件中包含temperature.h文件;

2、其次,由于我们这个模块是个温度处理模块,因此我们需要定义如下三个模块,以便其他模块使用本模块的变量。所以需要在temperature.c文件中定义如下三个变量;

 

u16 current_temperature = 0;//用来保存当前温度值

u16 current_AD = 0;//当前温度值对应的NTC的AD值

u16 next_temperature = 0;//上一次采样温度

 

定义了如上三个变量以后,我们需要在temperature.h文件中声明如上三个变量为外部变量,只有这样,其他模块才能使用temperature.c文件里面定义的变量,因此需要在temperature.h文件中增加如下三行代码。

 

extern u16 current_temperature;

extern u16 current_AD;

extern u16 next_temperature;

 

以上三个变量就是本模块定义的全局外部变量,剩下的一些其他变量就是本模块的静态变量了,只供本模块使用,接下来的工作就是要编写程序,将采集到的值赋值给以上三个全局外部变量了。

 

  1. 、根据第二篇帖子的原理,大家先把NTC阻值表里面,从0到100度对应的电阻值输入EXCEL表,然后把1024和10K电阻输入excel,利用EXCEL工具,可以快速的计算出每个温度对应的AD值,本项目将AD值扩大了10倍。通过计算,得出AD值表如下表:

u16 code tab_AD_to_temperature[] = {

  1938,2052,2172,2298,2430,2568,2673,2782,2894,3009,                                 //0   - 9

  3128,3273,3424,3580,3742,3909,4084,4265,4452,4645,                                 //10  - 19

  4845,5053,5267,5489,5717,5952,6193,6441,6696,6958,                               //20  - 29

  7227,7509,7799,8096,8401,8714,9030,9355,9687,10026,                               //30  - 39

  10373,10733,11100,11475,11858,12248,12650,13060,13477,13902, //40  - 49

  14276,14770,15213,15663,16119,16582,17049,17522,18000,18483, //50  - 59

  18971,19459,19951,20447,20947,21450,21963,22479,22998,23519, //60  - 69

  24042,24557,25074,25592,26110,26629,27176,27724,28270,28817, //70  - 79

  29362,29898,30432,30966,31496,32025,32552,33076,33596,34114, //80  - 89

  34629,35146,35658,36168,36672,37173,37656,38133,38607,39075, //90  - 99

  39539,40012,40479,40942,41397,41849,42289,42722,43150,43572, //100 - 109

  43987,44401,44808,45210,45603,45990,46371,46748,47114,47480, //110 - 119

  47833,48195,48552,48900,49242,49577,49909,50231,50548,50858, //120 - 129

  51164,51441,51713,51984,52245,52504,52754,53001,53247,53486, //130 - 139

  53718,53957,54193,54423,54650,54869,55086,55300,55506,55709, //140 - 149

  55909                                                                                                                                     //150

};

有了上表,就可以通过查表的方式,得到当前的奶温温度了。

  1. 、温度处理函数如下,大家根据注释理解吧,不懂得可以跟帖回复。

/***************************************************************************************

名    称:process_temperature

功    能:温度进程

参    数:无

返    回:无                                                                          

***************************************************************************************/

void process_temperature(void)

{

          //以下变量全部为本函数的静态变量

       static u8 process_temperature_statu = 0;//进程状态

       static u32 ADC_sum = 0;//ADC总和

       static u8 ADC_count = 0;//ADC采集次数

       static u16 AD_max = 0;//AD最大值

       static u16 AD_min = 0;//AD最小值

 

       u8 i;

       u16 tmp = 0;

 

  switch (process_temperature_statu){

           case 0:

                     tmp = get_ADC_val(ADC_CH_7);//获取NTC通道AD值

                     if (!ADC_count){//如果ADC_count为0,则把第一次的值作为最大最小值

                              AD_max = tmp;

                              AD_min = tmp;

                     }else{//反之处理最大最小值

                              if (tmp > AD_max){//如果当前值大于上一次值,则更新最大值变量

                                       AD_max = tmp;

                              }

 

                              if (tmp < AD_min){//如果当前值小于上一次值,则更新最小值变量

                                       AD_min = tmp;

                              }

                     }

 

                    ADC_sum += tmp;//计算采集AD值总和

                     ADC_count++;//采集次数自加

                     if (ADC_count >= 66){//总共采集66次,去掉最大值最小值,计算平均值作//为本次AD值,根据AD值计算当前温度

                              ADC_sum -= AD_max;//减去最大值

                              ADC_sum -= AD_min;//减去最小值

 

                              tmp = ADC_sum;

                             

                              current_AD = tmp / (66 - 2);//计算平均值为当前//AD值

                              process_temperature_statu = 1;//跳转到状态1处理其他工作

                     }

                     break;

           case 1:

                     tmp = ADC_sum;//将64次AD值付给tmp

                             

                     for (i = 0; i < TAB_TEMPERATURE_NUMBER; i++){//for循环查表,看看当前//AD值的64倍在哪个范围

                              if((tmp>=tab_AD_to_temperature)&&(tmp< tab_AD_to_temperature[i + 1])){

                                       current_temperature = i * 10;//满足if条件,当前温度为i度,并//扩大10倍

                                        current_temperature += (((tmp - tab_AD_to_temperature) * 10) / (tab_AD_to_temperature[i + 1] - tab_AD_to_temperature));

                              }

                     }

                    

                     if (tmp < tab_AD_to_temperature[0]){

                              current_temperature = 0;

                     }

 

                     if (tmp >= tab_AD_to_temperature[TAB_TEMPERATURE_NUMBER]){

                              current_temperature = TAB_TEMPERATURE_NUMBER * (u16)10;

                     }

                             

                     ADC_sum = 0;

                     ADC_count = 0;

                     process_temperature_statu = 0;//处理完成返回状态0重新采集温度

                     break;

           default:

                     process_temperature_statu = 0;

                     break;

         }

  }

二、NTC故障处理部分代码:

由于功能规格书里面要求有NTC故障检测功能,因此我们还需要编写NTC故障报警处理程序。所以我们要新建check_self.h和check_self.c文件作为故障处理模块。由于要记录各种系统故障,所以我们需要在check_self.c文件中定义如下变量:

u8 error_num = 0;//错误代码变量;0:正常;1:NTC故障;2:干烧故障;3:初始//奶温过高故障。

由于error_num变量需要供外部模块调用,因此需要在check_self.h头文件中声明为外部变量,方法和温度处理模块一样。

下面直接贴出NTC故障报警处理代码:

/***************************************************************************************

名    称:check_NTC

功    能:检查NTC

参    数:无

返    回:无                                                                          

***************************************************************************************/

void check_NTC(void)

{

  static u8 process_check_NTC_statu = 0;//静态变量,NTC故障处理状态变量

  static u16 process_check_NTC_count = 0;//计时变量

 

  process_check_NTC_count++;//计时变量自加,2ms自加一次

  switch (process_check_NTC_statu){

           case 0:

                     if (process_check_NTC_count >= 68){//延时,确保//AD采集完成

                              process_check_NTC_count = 0;

                              process_check_NTC_statu = 1;//跳到状态1处理        

                     }

                     break;

           case 1:

                     if (current_AD <= 3 || current_AD >= 1021){//NTC开路或者短路故障检测,//当前AD值小于4或者大于1020,则判断NTC故障

                              set_standy_statu();//恢复所有变量为初始值

                              error_num = 1;

 

                              PIN_LED_BUBBLE_BLUE = 0;//蓝灯亮

                              PIN_LED_BUBBLE_RED = 1;//红灯灭

 

                              process_check_NTC_count = 0;

                              process_check_NTC_statu = 2;//跳到状态2处理        

                     }

                     break;

           case 2://只有断电才能恢复process_check_NTC_statu为0

                     if (process_check_NTC_count >= 250){//执行NTC故障报警,500ms翻     //转LED状态

                              PIN_LED_BUBBLE_RED = !PIN_LED_BUBBLE_RED;

                              PIN_LED_BUBBLE_BLUE = !PIN_LED_BUBBLE_BLUE;

 

                              process_check_NTC_count = 0;//清楚计时变量  

                     }

                     break;

           default:

                     break;      

  }                

}

好了,相信大家看完源代码已经清楚了NTC采集温度的处理方法了,是不是觉得很简单啊。采集到了实际奶温后,上面的逻辑控制,温度控制程序就比较好写了。大家有没有注意到使用switch-case语句编程很简单啊,这就是传说中所谓的状态机编程,状态机就是把一个任务切割成一个一个小的部分处理,小的处理完成了,综合起来就变成完整的功能了,而且使用状态机编程,程序结构清晰明了,容易找BUG。下一讲我会讲按键逻辑部分代码,希望大家喜欢。

由于这里面不太好编辑文档,大家可以下载附件阅读。

文章评论0条评论)

登录后参与讨论
我要评论
0
20
关闭 站长推荐上一条 /2 下一条