基于stm32f103c8t6的红外测温仪代码
时间: 2023-08-23 16:05:39 浏览: 118
以下为基于STM32F103C8T6的红外测温仪的代码,主要使用了STM32的定时器、ADC、UART等模块:
```c
#include "stm32f10x.h"
#include "stdio.h"
#define USART_REC_LEN 20 //定义串口接收缓冲区大小
#define TEMP_AMBIENT_ADDR 0x00 //环境温度寄存器地址
#define TEMP_OBJECT_ADDR 0x01 //物体温度寄存器地址
uint8_t USART_RX_BUF[USART_REC_LEN]; //串口接收缓冲区
uint16_t USART_RX_STA = 0; //串口接收状态标志
void USART1_Init(void)
{
USART_InitTypeDef USART_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE); //使能USART1、GPIOA时钟
//USART1_TX PA.9
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化PA9
//USART1_RX PA.10
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //PA.10
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空输入
GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化PA10
//USART1 初始化设置
USART_InitStructure.USART_BaudRate = 115200; //波特率设置
USART_InitStructure.USART_WordLength = USART_WordLength_8b; //字长为8位数据格式
USART_InitStructure.USART_StopBits = USART_StopBits_1; //一个停止位
USART_InitStructure.USART_Parity = USART_Parity_No; //无奇偶校验位
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //无硬件数据流控制
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收发模式
USART_Init(USART1, &USART_InitStructure); //初始化串口1
USART_Cmd(USART1, ENABLE); //使能串口1
}
void TIM3_Init(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //TIM3时钟使能
TIM_TimeBaseStructure.TIM_Period = 199; //定时器周期200us
TIM_TimeBaseStructure.TIM_Prescaler = 71; //预分频器72,即72MHz/72 = 1MHz
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
TIM_Cmd(TIM3, ENABLE); //使能TIM3
}
void ADC1_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
ADC_InitTypeDef ADC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOA, ENABLE); //使能ADC1、GPIOA时钟
//PA.0 作为模拟通道输入引脚
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; //模拟输入
GPIO_Init(GPIOA, &GPIO_InitStructure);
//ADC1 初始化设置
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; //独立模式
ADC_InitStructure.ADC_ScanConvMode = DISABLE; //单通道模式
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; //单次转换模式
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; //软件触发转换
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //右对齐
ADC_InitStructure.ADC_NbrOfChannel = 1; //1个转换在规则序列中
ADC_Init(ADC1, &ADC_InitStructure);
//使能指定的ADC1的DMA传输
ADC_DMACmd(ADC1, ENABLE);
//启动ADC1校准
ADC_ResetCalibration(ADC1); //复位校准寄存器
while (ADC_GetResetCalibrationStatus(ADC1))
; //等待校准寄存器复位完成
ADC_StartCalibration(ADC1); //开始校准
while (ADC_GetCalibrationStatus(ADC1))
; //等待校准完成
//开启ADC1
ADC_Cmd(ADC1, ENABLE);
}
uint16_t Get_Adc(uint8_t ch)
{
//设置指定ADC的规则组通道,一个序列,采样时间
ADC_RegularChannelConfig(ADC1, ch, 1, ADC_SampleTime_239Cycles5);
//启动指定的ADC转换
ADC_SoftwareStartConvCmd(ADC1, ENABLE);
//等待转换完成
while (!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC))
;
//返回最近一次ADC1规则组的转换结果
return ADC_GetConversionValue(ADC1);
}
uint16_t readTemp(uint8_t addr)
{
uint16_t data;
I2C_Start();
I2C_Send_Byte(0x5a << 1 | 0); //发送写命令
if (I2C_Wait_Ack() != 0)
return 0xffff; //接收应答失败,退出
I2C_Send_Byte(addr); //发送寄存器地址
I2C_Wait_Ack(); //等待应答
I2C_Start(); //重新启动一次总线
I2C_Send_Byte(0x5a << 1 | 1); //发送读命令
I2C_Wait_Ack(); //等待应答
data = I2C_Read_Byte(0); //读取数据
I2C_Stop(); //停止总线
return data;
}
void USART1_IRQHandler(void)
{
if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
{
static uint8_t i = 0;
USART_RX_BUF[i++] = USART_ReceiveData(USART1);
if (USART_RX_BUF[i - 1] == '\n') //接收到换行符
{
USART_RX_STA |= 1 << 15; //标志接收完成
USART_RX_BUF[i - 1] = 0; //将换行符替换为字符串结束符
i = 0; //重新开始接收
}
}
}
void USART_Send_Str(char *str)
{
while (*str)
{
while ((USART1->SR & 0X40) == 0) //等待上一次发送完成
;
USART1->DR = (u8)*str++;
}
}
int main(void)
{
uint16_t raw;
float temp_ambient, temp_object;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //优先级分组设置
USART1_Init(); //初始化串口1
TIM3_Init(); //初始化定时器3
ADC1_Init(); //初始化ADC1
I2C_GPIO_Config(); //初始化I2C总线
delay_init(); //延时函数初始化
while (1)
{
TIM_SetCounter(TIM3, 0); //计数器清零
GPIO_ResetBits(GPIOA, GPIO_Pin_6); //拉低SCL
while (TIM_GetCounter(TIM3) < 5); //等待5us
GPIO_SetBits(GPIOA, GPIO_Pin_6); //拉高SCL
while (TIM_GetCounter(TIM3) < 10); //等待10us
GPIO_ResetBits(GPIOA, GPIO_Pin_6); //拉低SCL
raw = Get_Adc(0); //采集环境温度
temp_ambient = (float)raw * 3.3 / 4096 * 100 - 273.15; //计算环境温度
raw = readTemp(TEMP_OBJECT_ADDR); //读取物体温度
if (raw == 0xffff) //读取失败
{
USART_Send_Str("read object temperature failed!\r\n");
delay_ms(1000);
continue;
}
temp_object = (float)(raw & 0x7fff) * 0.02 - 273.15; //计算物体温度
if (raw & 0x8000) //负温度
{
temp_object = -temp_object;
}
printf("ambient temperature:%.2fC, object temperature:%.2fC\r\n", temp_ambient, temp_object);
delay_ms(1000);
}
}
```
在此代码中,我们使用了定时器3来产生红外测温仪所需的时序信号,使用ADC1来采集环境温度,使用I2C总线读取红外传感器的物体温度。同时,我们通过串口1将温度数据发送至PC端进行显示。
阅读全文