一、作品简介:
代码语言:txt复制 我们在开发加热不燃烧烟具的过程中,需要吧烟具内部的温度加到一个比较高的温度(200-300摄氏度),烟具内部本身有测温器件,但是不能保证烟具自己测试的温度就是准确的,所以就需要一个外部也要增加设备来辅助测试一下,并且把整个加热过程中的温度变化画出曲线,有助于对整个设备的研究。所以我们这次开发所用的硬件除了赤兔CH32V307开发板以外,还增加一个NTC的检测电路。如下图所示:
二、软件开发过程
1、软件环境
此次开发和编译坏境是沁恒微的MounRiver Studio软件,此软件用熟了感觉你keil好用太多了,并且还是免费的开发软件。具体如何好,只有真正使用来开发的各位工程师能明白,在此就不多说了。界面如下图所示:
2、基础例程测试:
本次设计的基础例程是本次活动提供的例程“TencentOS_DVP”。此代码已经包含了LCD屏的驱动,摄像头的驱动,以及AT指令以及MQTT协议等功能。只要稍加运用就可以做成一个可以连上腾讯云的网络产品。如下图所示就是本次测试连到腾讯云的日志记录:
3、云端开发:
根据学习视频和PPT学习,自己测试了一些简单的测试开发,开发还是比较方便的。只是时间紧,工作忙,没有实际真正开发成产品,等忙完这段时间,过段时间直接在公司立个预研项目直接开发,从此一个单片机工程师转变成一个全能物联网工程师还是有可能的。开发小程序如下图所示:
4、温度检测程序实现
NTC的温度检测,其原理就是使用热敏电阻的特性,根据厂家给出的热敏电阻对应温度参数,然后设计一个电路,使用电阻分压的情况下读取分压电阻的电压值,从而查表得出测试环境的实际温度值。程序代码如下:
代码语言:javascript复制#include "debug.h"
#include "tos_k.h"
#include "lcd.h"
#include "lcd_init.h"
#include "user_read_temperature.h"
#define M_COUNT_OF(Obj) (sizeof(Obj) / sizeof(Obj[0]))//总长度除以个体长度等于个数
Dev_ADC vDev_ADC;
s16 Calibrattion_Val = 0;
const uint16_t list_N_V[330] =
{
4090,4089,4089,4088,4088,4087,4087,4086,4086,4085,
4085,4084,4083,4083,4082,4081,4080,4080,4079,4078,
4077,4076,4075,4074,4073,4071,4070,4069,4067,4066,
4065,4063,4061,4060,4058,4056,4054,4052,4050,4048,
4046,4044,4041,4039,4036,4034,4031,4028,4025,4022,
4019,4015,4012,4008,4004,4000,3996,3992,3988,3983,
3978,3973,3968,3963,3958,3952,3946,3940,3934,3927,
3921,3914,3907,3899,3892,3884,3876,3868,3859,3850,
3841,3832,3822,3812,3802,3791,3781,3770,3758,3747,
3735,3722,3710,3697,3684,3670,3656,3642,3628,3613,
3598,3582,3566,3550,3534,3517,3500,3482,3464,3446,
3427,3409,3389,3370,3350,3330,3309,3288,3267,3246,
3224,3201,3178,3154,3131,3107,3082,3058,3033,3007,
2982,2956,2930,2904,2877,2851,2824,2797,2770,2742,
2714,2687,2659,2631,2603,2574,2546,2517,2489,2460,
2414,2368,2340,2312,2284,2255,2227,2199,2171,2143,
2115,2087,2059,2031,2004,1976,1949,1922,1895,1868,
1841,1815,1788,1762,1737,1711,1685,1660,1635,1610,
1585,1561,1537,1514,1491,1467,1445,1422,1400,1377,
1355,1334,1312,1291,1270,1249,1229,1209,1189,1169,
1150,1131,1112,1093,1075,1057,1039,1021,1004,987 ,
970 ,954 ,937 ,921 ,905 ,890 ,874 ,859 ,845 ,830 ,
815 ,801 ,787 ,773 ,760 ,747 ,734 ,721 ,709 ,696 ,
684 ,672 ,661 ,649 ,638 ,626 ,616 ,605 ,594 ,584 ,
574 ,564 ,554 ,545 ,535 ,526 ,517 ,508 ,499 ,490 ,
482 ,474 ,465 ,457 ,450 ,442 ,434 ,427 ,420 ,413 ,
405 ,398 ,392 ,385 ,379 ,372 ,366 ,360 ,354 ,348 ,
342 ,336 ,331 ,325 ,320 ,315 ,309 ,304 ,299 ,294 ,
289 ,285 ,280 ,276 ,271 ,267 ,262 ,258 ,254 ,250 ,
245 ,242 ,238 ,234 ,230 ,226 ,223 ,220 ,216 ,213 ,
209 ,206 ,203 ,200 ,197 ,194 ,191 ,188 ,185 ,182 ,
179 ,176 ,174 ,171 ,168 ,166 ,163 ,161 ,159 ,156 ,
153 ,151 ,149 ,147 ,145 ,143 ,140 ,138 ,136 ,135 ,
};
int uGetHeaterTemperature(uint8_t ch)//NTC测温
{
int data_len,x=0;
static uint16_t Adcn;
data_len=M_COUNT_OF(list_N_V);
Adcn = vDev_ADC.Read_ADC[ch];//userADC_var.ADC_uDATA[ch];
if((Adcn<=list_N_V[0])&&(Adcn>=list_N_V[data_len-1]))
{
for(x=0;x<data_len-1;x )
{
if(Adcn>=list_N_V[x])
{
break;
}
}
}
return x;
}
/*********************************************************************
* @fn ADC_Function_Init
*
* @brief Initializes ADC collection.
*
* @return none
*/
void ADC_Function_Init(void)
{
ADC_InitTypeDef ADC_InitStructure={0};
GPIO_InitTypeDef GPIO_InitStructure={0};
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE );
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE );
RCC_ADCCLKConfig(RCC_PCLK2_Div8);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_Init(GPIOB, &GPIO_InitStructure);
ADC_DeInit(ADC1);
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
ADC_InitStructure.ADC_ScanConvMode = DISABLE;
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_NbrOfChannel = 1;
ADC_Init(ADC1, &ADC_InitStructure);
ADC_DMACmd(ADC1, ENABLE);
ADC_Cmd(ADC1, ENABLE);
ADC_BufferCmd(ADC1, DISABLE); //disable buffe
ADC_ResetCalibration(ADC1);
while(ADC_GetResetCalibrationStatus(ADC1));
ADC_StartCalibration(ADC1);
while(ADC_GetCalibrationStatus(ADC1));
Calibrattion_Val = Get_CalibrationValue(ADC1);
ADC_BufferCmd(ADC1, ENABLE); //enable buffe
}
/*********************************************************************
* @fn Get_ADC_Val
*
* @brief Returns ADCx conversion result data.
*
* @param ch - ADC channel.
* ADC_Channel_0 - ADC Channel0 selected.
* ADC_Channel_1 - ADC Channel1 selected.
* ADC_Channel_2 - ADC Channel2 selected.
* ADC_Channel_3 - ADC Channel3 selected.
* ADC_Channel_4 - ADC Channel4 selected.
* ADC_Channel_5 - ADC Channel5 selected.
* ADC_Channel_6 - ADC Channel6 selected.
* ADC_Channel_7 - ADC Channel7 selected.
* ADC_Channel_8 - ADC Channel8 selected.
* ADC_Channel_9 - ADC Channel9 selected.
* ADC_Channel_10 - ADC Channel10 selected.
* ADC_Channel_11 - ADC Channel11 selected.
* ADC_Channel_12 - ADC Channel12 selected.
* ADC_Channel_13 - ADC Channel13 selected.
* ADC_Channel_14 - ADC Channel14 selected.
* ADC_Channel_15 - ADC Channel15 selected.
* ADC_Channel_16 - ADC Channel16 selected.
* ADC_Channel_17 - ADC Channel17 selected.
*
* @return none
*/
u16 Get_ADC_Val(u8 ch)
{
u16 val;
ADC_RegularChannelConfig(ADC1, ch, 1, ADC_SampleTime_239Cycles5 );
ADC_SoftwareStartConvCmd(ADC1, ENABLE);
while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC ));
val = ADC_GetConversionValue(ADC1);
return val;
}
/*********************************************************************
* @fn DMA_Tx_Init
*
* @brief Initializes the DMAy Channelx configuration.
*
* @param DMA_CHx - x can be 1 to 7.
* ppadr - Peripheral base address.
* memadr - Memory base address.
* bufsize - DMA channel buffer size.
*
* @return none
*/
void DMA_Tx_Init( DMA_Channel_TypeDef* DMA_CHx, u32 ppadr, u32 memadr, u16 bufsize)
{
DMA_InitTypeDef DMA_InitStructure={0};
RCC_AHBPeriphClockCmd( RCC_AHBPeriph_DMA1, ENABLE );
DMA_DeInit(DMA_CHx);
DMA_InitStructure.DMA_PeripheralBaseAddr = ppadr;
DMA_InitStructure.DMA_MemoryBaseAddr = memadr;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
DMA_InitStructure.DMA_BufferSize = bufsize;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init( DMA_CHx, &DMA_InitStructure );
}
/*********************************************************************
* @fn Get_ConversionVal
*
* @brief Get Conversion Value.
*
* @param val - Sampling value
*
* @return val Calibrattion_Val - Conversion Value.
*/
u16 Get_ConversionVal(s16 val)
{
if((val Calibrattion_Val)<0) return 0;
if((Calibrattion_Val val)>4095||val==4095) return 4095;
return (val Calibrattion_Val);
}
void user_Read_ADC(void)
{
uint8_t temp_D[50];
u16 ADC_Buf[1],Temperature[2];
ADC_Function_Init();
printf("CalibrattionValue:%dn", Calibrattion_Val);
while(1)
{
ADC_Buf[0] = Get_ADC_Val(ADC_Channel_8);
//Temperature[1] = TempSensor_Volt_To_Temper(Get_ADC_Val(ADC_Channel_TempSensor));
vDev_ADC.Read_ADC[0] = Get_ConversionVal(ADC_Buf[0]);
Temperature[0] = uGetHeaterTemperature(ADC_CH8);
sprintf(temp_D,"%d ",Temperature[0] );
printf("Temperature:%drn", Temperature[0]);
LCD_ShowString(30,140 16 16 16,"T=:",YELLOW,BLACK,32,0);
LCD_ShowString(100,140 16 16 16,temp_D,BRRED,BLACK,32,0);
tos_task_delay(500);
}
}
5、测量结果
通过串口示波器软件打印出来分析,与我们设计的温度曲线基本吻合。打印的图如下所示:
6、视频展示测试过程:
三、开发总结
本次开发的TencentOS Tiny系统的最大优势在可以直接使用手上的硬件链接到腾讯云的工作。大大简化了开发的流程和工作量。只是对于之前只是做单片机开发的我来说,还是有难度的。因为之前连腾讯小程序都还没开发成功过。但是通钢这次的学习,发现了使用智能硬件联网并不是特别难的事情。后续将通过更多的学习,把单片机联网来开发。这样才能使自己不落后于这个时代。