硬件
STM32F4IGT6 + NTC C13879
软件
Keil5 + STM32CubeMX
所用外设
USART + ADC
电路图如图
用一个10K的电阻 用光敏电阻来代替NTC(主要在AD里没找到对应的器件),NTC在25℃下阻值为10K。
USART的配置
做一下重定向即可,主要是用printf()函数
将下面代码放在USART.C下即可
int fputc(int ch, FILE *f)
{
HAL_UART_Transmit(&huart2, (uint8_t *)&ch, 1, 0xffff);
return ch;
}
int fgetc(FILE *f)
{
uint8_t ch;
HAL_UART_Receive(&huart2, &ch, 1, 0xffff);
return ch;
}
ADC具体可看正点或野火官方论坛以及《STM32F4XX系列中文手册》
下面就说一下配置,调试的话可以去看ADC寄存器一章,写的很详细
ADC配置如下(我的板子使用的是3通道,该板子1通道坏了)
ADC的传输模式——扫描转换模式、不连续转换模式、连续转换模式,具体看手册。
ADC的通道配置——规则通道(Regular),注入通道(injected),简单的理解就是注入通道可以插队,规则通道不行。
使用ADC要注意转换时间和输入信号的变化时间,否则无法采集到正确的数据
ADC轮询式转换
void ADC_Value_Get(void)//轮询式发送
{
HAL_ADC_Start(&hadc1);
if(HAL_ADC_PollForConversion(&hadc1,100) == HAL_OK)
{
ADC_Value = HAL_ADC_GetValue(&hadc1);
ADC_Volt = ADC_Value*330/4095;
printf("电压值是 : %d.%d%d\n",ADC_Volt/100,ADC_Volt%100/10,ADC_Volt%10);
printf("此时的温度 :%d",Temp);
}
HAL_ADC_Stop(&hadc1);
}
(中断方式也一样不过配置上要勾上Intrruption 代码基本差不多,带IT就是中断 不带IT就是阻塞)
中断方式对CPU的占用率较低,相应的轮询法占用率很高
配置到这就结论 接下来就讲一下二分查找表法的思路吧
我使用利用matlab对数据预处理,得到不同温度下ADC理论应该采到值,但只是粗略的估算故取整
>> all_data = 10+data; %data为NTC在-25~71℃时的阻值
>> y = all_data.\data;
>> y_Value = 4095*y; %求不同温度是 ADC采到的Value
>> y_Value = round(y_Value); %取整
>> empty = [0,0,0];
>> y_Value1 = [y_Value,empty];
>> y_Value2 = reshape(y_Value1,10,10);
>> fid = fopen('b.txt','wt');
for i = 1:1:10
for j = 1:1:10
if j == 10
fprintf(fid,'%g\n,',y_Value2(j,i));
else
fprintf(fid,'%g,',y_Value2(j,i));
end
end
end
fclose(fid);
我们就会得到以下的数组
static const unsigned int NTC[size] =
{3773,3757,3740,3722,3703,3684,3664,3644,3622,3600,
3577,3553,3528,3502,3475,3448,3419,3390,3360,3329,
3297,3264,3230,3195,3160,3123,3086,3048,3010,2970,
2930,2889,2848,2806,2763,2720,2676,2633,2588,2544,
2499,2454,2408,2363,2317,2272,2226,2181,2136,2091,
2048,2001,1957,1913,1869,1826,1783,1741,1699,1657,
1617,1576,1537,1498,1459,1422,1385,1348,1312,1277,
1243,1209,1176,1144,1112,1081,1051,1022,993,965,
937,910,884,859,834,810,786,764,741,720,
699,679,659,639,621,602,585};// -25 ~ 71
所谓二分法,实际上就是对半查询,以此来确定我们ADC所采到的值,在那两个温度范围直接,然后根据不同的处理方式,取小,取大,或者线性处理都可
查询代码如下
int tempDetect(uint16_t Value)
{
int s=0,m=0,e=size;
if(Value < 585)
return -25;
else if(Value > 3773)
return 71;
else
{
while(s < e)//二分法进行查找
{
m = ((s+e)>>1);//右移一位 即除以2
if(Value < NTC[m])
s = m+1;
else
e = m;
}
return m-26;
}
}
然后把原来的代码加上下面两句代码
void ADC_Value_Get(void)//轮询式发送
{
HAL_ADC_Start(&hadc1);
if(HAL_ADC_PollForConversion(&hadc1,100) == HAL_OK)
{
ADC_Value = HAL_ADC_GetValue(&hadc1);
ADC_Volt = ADC_Value*330/4095;
Temp = tempDetect(ADC_Value);
printf("ADC的值是 : %d\n",ADC_Value);
printf("电压值是 : %d.%d%d\n",ADC_Volt/100,ADC_Volt%100/10,ADC_Volt%10);
printf("此时的温度 :%d",Temp);
}
HAL_ADC_Stop(&hadc1);
}
最后在int main()中写入
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
ADC_Value_Get();
HAL_Delay(1000);
}
最后上板调试即可。