自己动手做烟温气复合锂电池热失控探测器(第四篇 锂电池热失控探测器单片机代码展示(库函数))

首先我写的代码是参考正点原子的库函数源代码,其形式与正点原子源代码保持一致。HARDWARE文件夹中为每一个传感器,包括CAN通讯都新建了一个源文件和头文件,方便主程序直接引用,如下图

那我们来一个个展示:
1.NTC热敏电阻,其采用是adc(PA1)采集:

头文件adc.h

#include "stm32f10x.h"
#include <math.h>

#define  NUMSAMP   640
#define  NUMHEAD   40
#define  TEMPMAX   4090
#define  TEMPMIN   0

extern  void ADC1_Init(void);
extern  void StartADC(void);
extern  void StopADC(void);
extern  float  HandleADCTemp(void);

源文件adc.c

#include "stm32f10x.h"
#include "adc.h"
#include "delay.h"

volatile unsigned int  ADC_Buf[NUMSAMP+1];      //放单片机ADC采集原始值
volatile unsigned int  ADC_BufCnt=0;            //采集量变量

 /**************************************************************************************
 * 描  述 : 初始化ADC1
 * 入  参 : 无
 * 返回值 : 无
 **************************************************************************************/
void ADC1_Init(void)
{
	GPIO_InitTypeDef        GPIO_InitStructure;
	ADC_InitTypeDef 				ADC_InitStructure;
	NVIC_InitTypeDef				NVIC_InitStructure;

	RCC_APB2PeriphClockCmd( RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOA, ENABLE);  //使能ADC1用时钟和PA口时钟
	RCC_ADCCLKConfig(RCC_PCLK2_Div6);                                       //设置ADC分频因子为6,ADCCLK=PCLK2/6
	
	//配置PA1为模拟通道输入引脚
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;	
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;                            //模拟输入   
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	ADC_DeInit(ADC1);                                                       //将外设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转换
	ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;                   //右对齐	
	ADC_InitStructure.ADC_NbrOfChannel = 1;                                  //转换ADC通道的数目为1
	ADC_Init(ADC1, &ADC_InitStructure);
	
	ADC_DMACmd(ADC1,DISABLE);                                                //失能ADC1的DMA请求 
	ADC_ITConfig(ADC1, ADC_IT_EOC,ENABLE);                                   //使能ADC1中断
 	ADC_Cmd(ADC1,ENABLE);                                                    // 使能ADC1   
  
	ADC_ResetCalibration(ADC1);                                              //重置指定的ADC的校准寄存器 	
	while(ADC_GetResetCalibrationStatus(ADC1));                              //获取ADC重置校准寄存器的状态  

	ADC_StartCalibration(ADC1);                                              //开始指定ADC的校准状态
	while(ADC_GetCalibrationStatus(ADC1));                                   //获取指定ADC的校准程序
	
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);                          //NVIC_Group:先占优先级2位,从优先级2位
	NVIC_InitStructure.NVIC_IRQChannel = ADC1_2_IRQn;	                       //配置为ADC1_2中断
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2;                  //先占优先级为2
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;	                     //从优先级为3
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;                          //使能中断通道
	NVIC_Init(&NVIC_InitStructure);	 
}

 /**************************************************************************************
 * 描  述 : 启动指定的ADC通道开始AD转换
 * 入  参 : 无
 * 返回值 : 无
 **************************************************************************************/
void StartADC(void)
{
	ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 1, ADC_SampleTime_239Cycles5);   //开通通道3,即PA3
  	
	ADC_ITConfig(ADC1, ADC_IT_EOC,ENABLE);                                         //使能ADC1中断
	ADC_Cmd(ADC1,ENABLE);                                                          //把ADC从断电模式下唤醒
	delay_ms(1);                                                 //在转换器上电至转换开始有一个延时tSTAB  
  ADC_SoftwareStartConvCmd(ADC1, ENABLE);                                        //软件触发ADC转换 	
}

 /**************************************************************************************
 * 描  述 : 关闭ADC1
 * 入  参 : 无
 * 返回值 : 无
 **************************************************************************************/
void StopADC(void)
{
	ADC_ITConfig(ADC1, ADC_IT_EOC,DISABLE);             //关闭ADC1中断
	ADC_Cmd(ADC1,DISABLE);                              // 关闭ADC1 
}

 /**************************************************************************************
 * 描  述 : ADC1中断服务函数
 * 入  参 : 无
 * 返回值 : 无
 **************************************************************************************/
void ADC1_2_IRQHandler(void)
{  
	unsigned int adcPtr;
	
  if(ADC_GetITStatus(ADC1,ADC_IT_EOC) ==SET)      //检查指定的ADC中断是否发生
  {  
	  adcPtr=ADC_GetConversionValue(ADC1);          //读取ADC1转换值
	  ADC_Buf[ADC_BufCnt++]=adcPtr;                 //将读取的ADC1转换值存入指定数组
	  if(ADC_BufCnt==NUMSAMP)                       //指定数量的ADC1信息采集结束
    { 
		  ADC_BufCnt=0;		                            //清零采集量变量值
	  }
	  ADC_ClearITPendingBit(ADC1,ADC_IT_EOC);       //清除ADC1中的中断待处理位
  }
}
 
 /**************************************************************************************
 * 描  述 : 采集处理函数
 * 入  参 : 无
 * 返回值 : 温度值
 **************************************************************************************/
float HandleADCTemp(void)
{
	unsigned long val=0;
	unsigned int Temp_signal;
	unsigned int i;
	float g_temperature;

  
  //软件过滤采集的原始值的前NUMHEAD和最后NUMHEAD个数据,将剩余数据累加
	for(i=NUMHEAD;i<(NUMSAMP-NUMHEAD);i++)  
	{
		val=val+ADC_Buf[i];
	}
  //对采集的累加值求平均
	Temp_signal=val/(NUMSAMP-2*NUMHEAD);  

	//下面是曲线拟合得到的温度与采集原始值之间的关系,仅供参考
	g_temperature=-(7.12E-016)*pow(Temp_signal,5)+(7.644E-012)*pow(Temp_signal,4)-(3.401E-08)*pow(Temp_signal,3)+(7.898E-05)*pow(Temp_signal,2)-(1.182E-01)*Temp_signal+(1.20E+02);

  //返回温度值
	return g_temperature;	
}
 
/*************************************END OF FILE******************************/

2.烟雾传感器(USART2):

头文件SMOKE.h

#include "stdio.h"	
#include "sys.h" 


void My_USART2_Init(u32 bound);
void USART2_IRQHandler(void);
extern u8 SMOKE_buf[4];

源文件SMOKE.c

#include "delay.h"
#include "sys.h"	
#include "SMOKE.h"	
#include "stdio.h"
#include "math.h"
#include "string.h"

u8 USART2_RX_BUF[9]={0};//
u16 USART2_RX_STA=0;//



//USART2传输烟雾探测器数据
void My_USART2_Init(u32 bound)
{
	GPIO_InitTypeDef GPIO_Initstrue;
	USART_InitTypeDef USART_Initstrue;
	NVIC_InitTypeDef NVIC_InitStrue;
	
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);	//使能USART2,GPIOA时
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);	//使能GPIOA时钟
	
	//USART2_TX   GPIOA.2
	GPIO_Initstrue.GPIO_Mode=GPIO_Mode_AF_PP; 
	GPIO_Initstrue.GPIO_Pin=GPIO_Pin_2;//PA.2
	GPIO_Initstrue.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_Initstrue);
	
	//USART2_RX   GPIOA.3
	GPIO_Initstrue.GPIO_Mode=GPIO_Mode_IN_FLOATING; 
	GPIO_Initstrue.GPIO_Pin=GPIO_Pin_3;//PA.3
	GPIO_Initstrue.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_Initstrue);
	
	//USART2 初始化设置
	USART_Initstrue.USART_BaudRate = bound;//串口波特率
	USART_Initstrue.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
	USART_Initstrue.USART_StopBits = USART_StopBits_1;//一个停止位
	USART_Initstrue.USART_Parity = USART_Parity_No;//无奇偶校验位
	USART_Initstrue.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制
	USART_Initstrue.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;	//收发模式
  USART_Init(USART2, &USART_Initstrue); //初始化串口2
	
	//Usart2 NVIC 配置
  NVIC_InitStrue.NVIC_IRQChannel = USART2_IRQn;
	NVIC_InitStrue.NVIC_IRQChannelPreemptionPriority=3 ;//抢占优先级3
	NVIC_InitStrue.NVIC_IRQChannelSubPriority = 0;		//子优先级1
	NVIC_InitStrue.NVIC_IRQChannelCmd = ENABLE;			//IRQ通道使能
	NVIC_Init(&NVIC_InitStrue);	//根据指定的参数初始化VIC寄存器
	
	

  USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);//开启串口接受中断
	USART_Cmd(USART2, ENABLE);                    //使能串口2 
}





static char  start_smoke=0; //
void USART2_IRQHandler(void) //
{
	 u8 Res=0;//
   if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET)  //
    {
        Res =USART_ReceiveData(USART2);	//  
	

			
			if(Res == 0x0a) //
            {
                 start_smoke=1;   //
            }

            if(start_smoke == 1)
            {
                USART2_RX_BUF[USART2_RX_STA] = Res ; //		
                USART2_RX_STA++;//
                if(USART2_RX_STA == 8 && (USART2_RX_BUF[4]==0x0b))//
                    {

								 SMOKE_buf[0] = USART2_RX_BUF[1];//蓝光前向
								 SMOKE_buf[1] = USART2_RX_BUF[2];//蓝光后向

								 SMOKE_buf[2] = USART2_RX_BUF[5];//红光前向
								 SMOKE_buf[3] = USART2_RX_BUF[6];//红光后向


                        USART2_RX_STA=0;//  
											  memset(USART2_RX_BUF,0,sizeof(USART2_RX_BUF));
					              start_smoke=0;
                    }
            } 
      
		}
}

3.CO传感器(USART3):

头文件CO.h

#include "stdio.h"	
#include "sys.h" 

void My_USART3_Init(u32 bound);
void USART3_IRQHandler(void);
extern u8 CO_data;

源文件CO.c

#include "delay.h"
#include "sys.h"	
#include "CO.h"	
#include "stdio.h"
#include "math.h"
#include "string.h"


//USART3传输CO数据
void My_USART3_Init(u32 bound)
{
	GPIO_InitTypeDef GPIO_Initstrue;
	USART_InitTypeDef USART_Initstrue;
	NVIC_InitTypeDef NVIC_InitStrue;
	
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);	//使能USART3,GPIOB时
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);	//使能GPIOB时钟
	
	//USART3_TX   GPIOB.10
	GPIO_Initstrue.GPIO_Mode=GPIO_Mode_AF_PP; 
	GPIO_Initstrue.GPIO_Pin=GPIO_Pin_10;//PB.10
	GPIO_Initstrue.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOB,&GPIO_Initstrue);
	
	//USART3_RX   GPIOB.11
	GPIO_Initstrue.GPIO_Mode=GPIO_Mode_IN_FLOATING; 
	GPIO_Initstrue.GPIO_Pin=GPIO_Pin_11;//PB.11
	GPIO_Initstrue.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOB,&GPIO_Initstrue);
	
	//USART3 初始化设置
	USART_Initstrue.USART_BaudRate = bound;//串口波特率
	USART_Initstrue.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
	USART_Initstrue.USART_StopBits = USART_StopBits_1;//一个停止位
	USART_Initstrue.USART_Parity = USART_Parity_No;//无奇偶校验位
	USART_Initstrue.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制
	USART_Initstrue.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;	//收发模式
  USART_Init(USART3, &USART_Initstrue); //初始化串口3
	
	//Usart1 NVIC 配置
  NVIC_InitStrue.NVIC_IRQChannel = USART3_IRQn;
	NVIC_InitStrue.NVIC_IRQChannelPreemptionPriority=3 ;//抢占优先级3
	NVIC_InitStrue.NVIC_IRQChannelSubPriority = 1;		//子优先级2
	NVIC_InitStrue.NVIC_IRQChannelCmd = ENABLE;			//IRQ通道使能
	NVIC_Init(&NVIC_InitStrue);	//根据指定的参数初始化VIC寄存器
	
	

  USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);//开启串口接受中断
	USART_Cmd(USART3, ENABLE);                    //使能串口3 
}



u8 USART3_RX_BUF[9];//
u16 USART3_RX_STA=0;//

static char  start_CO=0; //

void USART3_IRQHandler(void) //
{
	 u8 Res=0;//
   if(USART_GetITStatus(USART3, USART_IT_RXNE) != RESET)  //
    {
        Res =USART_ReceiveData(USART3);	//
        //     
			if(Res == 0xFF) //
            {
                 start_CO=1;   //
            }

            if(start_CO == 1)
            {
                USART3_RX_BUF[USART3_RX_STA] = Res ; //		
                USART3_RX_STA++;//
                if(USART3_RX_STA > 8 && (USART3_RX_BUF[1]==0x04))//
                    {
											  
                        CO_data = (USART3_RX_BUF[4]*256+USART3_RX_BUF[5])/2;//数值除以2
                        USART3_RX_STA=0;//  
                        USART3_RX_BUF[0] = 0;
					              start_CO=0;
                    }
            } 
        
		}

}

4.VOC传感器(UART4):

头文件VOC.h

#include "stdio.h"	
#include "sys.h" 

void My_USART4_Init(u32 bound);
void UART4_IRQHandler(void);
extern u8 VOC_data;

源文件VOC.c

#include "delay.h"
#include "sys.h"	
#include "VOC.h"	
#include "stdio.h"
#include "math.h"
#include "string.h"

//UART4传输VOC数据
void My_USART4_Init(u32 bound)
{
	GPIO_InitTypeDef GPIO_Initstrue;
	USART_InitTypeDef USART_Initstrue;
	NVIC_InitTypeDef NVIC_InitStrue;
	
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART4, ENABLE);	//使能USART4
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);	//使能GPIOC时钟
	
	//USART4_TX   GPIOC.10
	GPIO_Initstrue.GPIO_Mode=GPIO_Mode_AF_PP; 
	GPIO_Initstrue.GPIO_Pin=GPIO_Pin_10;//PC.10
	GPIO_Initstrue.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOC,&GPIO_Initstrue);
	
	//USART4_RX   GPIOC.11
	GPIO_Initstrue.GPIO_Mode=GPIO_Mode_IN_FLOATING; 
	GPIO_Initstrue.GPIO_Pin=GPIO_Pin_11;//PC.11
	GPIO_Initstrue.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOC,&GPIO_Initstrue);
	
	//USART3 初始化设置
	USART_Initstrue.USART_BaudRate = bound;//串口波特率
	USART_Initstrue.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
	USART_Initstrue.USART_StopBits = USART_StopBits_1;//一个停止位
	USART_Initstrue.USART_Parity = USART_Parity_No;//无奇偶校验位
	USART_Initstrue.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制
	USART_Initstrue.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;	//收发模式
  USART_Init(UART4, &USART_Initstrue); //初始化串口
	
	//Usart1 NVIC 配置
  NVIC_InitStrue.NVIC_IRQChannel = UART4_IRQn;
	NVIC_InitStrue.NVIC_IRQChannelPreemptionPriority=3 ;//抢占优先级3
	NVIC_InitStrue.NVIC_IRQChannelSubPriority = 2;		//子优先级2
	NVIC_InitStrue.NVIC_IRQChannelCmd = ENABLE;			//IRQ通道使能
	NVIC_Init(&NVIC_InitStrue);	//根据指定的参数初始化VIC寄存器
	
	

  USART_ITConfig(UART4, USART_IT_RXNE, ENABLE);//开启串口接受中断
	USART_Cmd(UART4, ENABLE);                    //使能串口4 
}



u8 USART4_RX_BUF[9];//
u16 USART4_RX_STA=0;//

static char  start_VOC=0; //

void UART4_IRQHandler(void) //
{
	 u8 Res=0;//
   if(USART_GetITStatus(UART4, USART_IT_RXNE) != RESET)  //
    {
        Res =USART_ReceiveData(UART4);	//
        //     
			if(Res == 0xFF) //
            {
                 start_VOC=1;   //
            }

            if(start_VOC == 1)
            {
                USART4_RX_BUF[USART4_RX_STA] = Res ; //		
                USART4_RX_STA++;//
                if(USART4_RX_STA > 8  && (USART4_RX_BUF[1]==0x34))//
                    {
											  
                        VOC_data = (USART4_RX_BUF[4]*256+USART4_RX_BUF[5])/5;//数值除以5
                        USART4_RX_STA=0;//  
                        USART4_RX_BUF[0] = 0;
					              start_VOC=0;
                    }
            } 
        
		}

}

5.H2传感器(UART5):

头文件H2.h

#include "stdio.h"	
#include "sys.h" 

void My_USART5_Init(u32 bound);
void UART5_IRQHandler(void);
extern u8 H2_data;

源文件H2.c

#include "delay.h"
#include "sys.h"	
#include "H2.h"	
#include "stdio.h"
#include "math.h"
#include "string.h"

//UART5传输H2数据
void My_USART5_Init(u32 bound)
{
	GPIO_InitTypeDef GPIO_Initstrue;
	USART_InitTypeDef USART_Initstrue;
	NVIC_InitTypeDef NVIC_InitStrue;
	
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART5, ENABLE);	//使能UART5
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);	//使能GPIOC时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD, ENABLE);	//使能GPIOD时钟
	
	//USART5_TX   GPIOC.12
	GPIO_Initstrue.GPIO_Mode=GPIO_Mode_AF_PP; 
	GPIO_Initstrue.GPIO_Pin=GPIO_Pin_12;//PC.12
	GPIO_Initstrue.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOC,&GPIO_Initstrue);
	
	//USART5_RX   GPIOD.2
	GPIO_Initstrue.GPIO_Mode=GPIO_Mode_IN_FLOATING; 
	GPIO_Initstrue.GPIO_Pin=GPIO_Pin_2;//PD.2
	GPIO_Initstrue.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOD,&GPIO_Initstrue);
	
	//USART5 初始化设置
	USART_Initstrue.USART_BaudRate = bound;//串口波特率
	USART_Initstrue.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
	USART_Initstrue.USART_StopBits = USART_StopBits_1;//一个停止位
	USART_Initstrue.USART_Parity = USART_Parity_No;//无奇偶校验位
	USART_Initstrue.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制
	USART_Initstrue.USART_Mode = USART_Mode_Rx | USART_Mode_Tx ;	//收发模式
  USART_Init(UART5, &USART_Initstrue); //初始化串口
	
	//Usart1 NVIC 配置
  NVIC_InitStrue.NVIC_IRQChannel = UART5_IRQn;
	NVIC_InitStrue.NVIC_IRQChannelPreemptionPriority=3 ;//抢占优先级3
	NVIC_InitStrue.NVIC_IRQChannelSubPriority = 3;		//子优先级2
	NVIC_InitStrue.NVIC_IRQChannelCmd = ENABLE;			//IRQ通道使能
	NVIC_Init(&NVIC_InitStrue);	//根据指定的参数初始化VIC寄存器
	
	

  USART_ITConfig(UART5, USART_IT_RXNE, ENABLE);//开启串口接受中断
	USART_Cmd(UART5, ENABLE);                    //使能串口4 
}



u8 USART5_RX_BUF[9];//
u16 USART5_RX_STA=0;//

static char  start_H2=0; //

void UART5_IRQHandler(void) //
{
	 u8 Res=0;//
			

   if(USART_GetITStatus(UART5, USART_IT_RXNE) != RESET)  //
    {
        Res =USART_ReceiveData(UART5);	//
			
			if(Res == 0xFF) //
            {
                 start_H2=1;   //
            }

            if(start_H2 == 1)
            {
                USART5_RX_BUF[USART5_RX_STA] = Res ; //		
                USART5_RX_STA++;//
                if(USART5_RX_STA > 8 && (USART5_RX_BUF[1]==0x06))//
                    {
											  
                        H2_data = (USART5_RX_BUF[4]*256+USART5_RX_BUF[5])/40;//数值除以40
                        USART5_RX_STA=0;//  
                        USART5_RX_BUF[0] = 0;
					              start_H2=0;
                    }
            } 
        
		}

}

6.CAN通讯

头文件CAN.h

#ifndef __CAN_H
#define __CAN_H	 
#include "sys.h"	    
							  

//CAN接收RX0中断使能
#define CAN_RX0_INT_ENABLE	0		//0,不使能;1,使能.								    
										 							 				    
u8 CAN_Mode_Init(u8 tsjw,u8 tbs2,u8 tbs1,u16 brp,u8 mode);//CAN初始化
 
u8 Can_Send_Msg(u8* msg,u8 len);						//发送数据

u8 Can_Receive_Msg(u8 *buf);							//接收数据

int Can_cmp(u8*buf1,u8*buf2);//比较ID函数
#endif

源文件CAN.c

#include "can.h"
#include "led.h"
#include "delay.h"
#include "usart.h"

//CAN初始化
//tsjw:重新同步跳跃时间单元.范围:CAN_SJW_1tq~ CAN_SJW_4tq
//tbs2:时间段2的时间单元.   范围:CAN_BS2_1tq~CAN_BS2_8tq;
//tbs1:时间段1的时间单元.   范围:CAN_BS1_1tq ~CAN_BS1_16tq
//brp :波特率分频器.范围:1~1024;  tq=(brp)*tpclk1
//波特率=Fpclk1/((tbs1+1+tbs2+1+1)*brp);
//mode:CAN_Mode_Normal,普通模式;CAN_Mode_LoopBack,回环模式;
//Fpclk1的时钟在初始化的时候设置为36M,如果设置CAN_Mode_Init(CAN_SJW_1tq,CAN_BS2_8tq,CAN_BS1_9tq,4,CAN_Mode_LoopBack);
//则波特率为:36M/((8+9+1)*4)=500Kbps
//返回值:0,初始化OK;
//    其他,初始化失败;


u8 CAN_Mode_Init(u8 tsjw,u8 tbs2,u8 tbs1,u16 brp,u8 mode)
{

	  GPIO_InitTypeDef GPIO_InitStructure; 
	  CAN_InitTypeDef        CAN_InitStructure;
 	  CAN_FilterInitTypeDef  CAN_FilterInitStructure;
#if CAN_RX0_INT_ENABLE 
   	NVIC_InitTypeDef  NVIC_InitStructure;
#endif

	  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//使能PORTA时钟	                   											 

  	RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);//使能CAN1时钟	

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;	//复用推挽
    GPIO_Init(GPIOA, &GPIO_InitStructure);		//初始化IO
   
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;//上拉输入
    GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化IO
	  
 	//CAN单元设置
 	  CAN_InitStructure.CAN_TTCM=DISABLE;						 //非时间触发通信模式  //
 	  CAN_InitStructure.CAN_ABOM=DISABLE;						 //软件自动离线管理	 //
  	CAN_InitStructure.CAN_AWUM=DISABLE;						 //睡眠模式通过软件唤醒(清除CAN->MCR的SLEEP位)//
  	CAN_InitStructure.CAN_NART=ENABLE;						 	//禁止报文自动传送 //
  	CAN_InitStructure.CAN_RFLM=DISABLE;						 //报文不锁定,新的覆盖旧的 // 
  	CAN_InitStructure.CAN_TXFP=DISABLE;						 //优先级由报文标识符决定 //
  	CAN_InitStructure.CAN_Mode= mode;	         //模式设置: mode:0,普通模式;1,回环模式; //
  	//设置波特率
  	CAN_InitStructure.CAN_SJW=tsjw;				//重新同步跳跃宽度(Tsjw)为tsjw+1个时间单位  CAN_SJW_1tq	 CAN_SJW_2tq CAN_SJW_3tq CAN_SJW_4tq
  	CAN_InitStructure.CAN_BS1=tbs1; //Tbs1=tbs1+1个时间单位CAN_BS1_1tq ~CAN_BS1_16tq
  	CAN_InitStructure.CAN_BS2=tbs2;//Tbs2=tbs2+1个时间单位CAN_BS2_1tq ~	CAN_BS2_8tq
  	CAN_InitStructure.CAN_Prescaler=brp;            //分频系数(Fdiv)为brp+1	//
  	CAN_Init(CAN1, &CAN_InitStructure);            // 初始化CAN1 

 	  CAN_FilterInitStructure.CAN_FilterNumber=0;	  //过滤器0
   	CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask; 
  	CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit; //32位 
  	CAN_FilterInitStructure.CAN_FilterIdHigh=0x0000;32位ID
  	CAN_FilterInitStructure.CAN_FilterIdLow=0x0000;
  	CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0x0000;//32位MASK
  	CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000;
  	CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_Filter_FIFO0;//过滤器0关联到FIFO0
 	  CAN_FilterInitStructure.CAN_FilterActivation=ENABLE; //激活过滤器0

  	CAN_FilterInit(&CAN_FilterInitStructure);//滤波器初始化
#if CAN_RX0_INT_ENABLE
	
	  CAN_ITConfig(CAN1,CAN_IT_FMP0,ENABLE);//FIFO0消息挂号中断允许.		    
  
  	NVIC_InitStructure.NVIC_IRQChannel = USB_LP_CAN1_RX0_IRQn;
  	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;     // 主优先级为1
  	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;            // 次优先级为0
  	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  	NVIC_Init(&NVIC_InitStructure);
#endif
	return 0;
}   
 
#if CAN_RX0_INT_ENABLE	//使能RX0中断
//中断服务函数			    
void USB_LP_CAN1_RX0_IRQHandler(void)
{
  	CanRxMsg RxMessage;
	int i=0;
    CAN_Receive(CAN1, 0, &RxMessage);
	for(i=0;i<8;i++)
	printf("rxbuf[%d]:%d\r\n",i,RxMessage.Data[i]);
}
#endif

//can发送一组数据(固定格式:ID为0X12,标准帧,数据帧)	
//len:数据长度(最大为8)				     
//msg:数据指针,最大为8个字节.
//返回值:0,成功;
//		 其他,失败;
u8 Can_Send_Msg(u8* msg,u8 len)
{	
  u8 mbox;
  u16 i=0;
  CanTxMsg TxMessage;
  TxMessage.StdId=0x12;					 // 标准标识符 
  TxMessage.ExtId=0x12;				   // 设置扩展标示符 
  TxMessage.IDE=CAN_Id_Standard; // 标准帧
  TxMessage.RTR=CAN_RTR_Data;		 // 数据帧
  TxMessage.DLC=len;						// 要发送的数据长度
  for(i=0;i<len;i++)
  TxMessage.Data[i]=msg[i];			          
  mbox= CAN_Transmit(CAN1, &TxMessage);   
  i=0;
  while((CAN_TransmitStatus(CAN1, mbox)==CAN_TxStatus_Failed)&&(i<0XFFF))i++;	//等待发送结束
  if(i>=0XFFF)return 1;
  return 0;		

}
//can口接收数据查询
//buf:数据缓存区;	 
//返回值:0,无数据被收到;
//		 其他,接收的数据长度;
u8 Can_Receive_Msg(u8 *buf)
{		   		   
 	u32 i;
	CanRxMsg RxMessage;
    if( CAN_MessagePending(CAN1,CAN_FIFO0)==0)return 0;		//没有接收到数据,直接退出 
    CAN_Receive(CAN1, CAN_FIFO0, &RxMessage);//读取数据	
    for(i=0;i<8;i++)
    buf[i]=RxMessage.Data[i];  
	return RxMessage.DLC;	
}

int Can_cmp(u8*buf1,u8*buf2)
{
	  int i=0;
		while(i<8)
		{
		if(buf1[i]!=buf2[i])//将接收到的数据与设置的数据比对,如果相等flag=1保持不变,否则flag=0
		{
		return 0;
		break;
		}
		else
		i++;
		}
		if(i==8)
		{
		return 1;
		}
		return 0;
}

7.最后主程序main.c

#include "delay.h"
#include "sys.h"	 
#include "adc.h"
#include "led.h"
#include "beep.h" 
#include "math.h"
#include "stdio.h"
#include "can.h"
#include "VOC.h"
#include "string.h"
#include "SMOKE.h"
#include "usart.h"
#include "H2.h"
#include "CO.h"


u8 total_buf[9]={0};
u8 arr[8]={0};
u8 SMOKE_buf[4];
u8 CO_data;
u8 VOC_data;
u8 H2_data;

 int main(void)
 {	 
  u8 ID[8]={0}; 
	u8 canbuf[8]; 
	ID[0]=0X0d;
	ID[1]=0X0d; 
	ID[2]=0X00;
	ID[3]=0X01; 
	ID[4]=0X00;
	ID[5]=0X00;
	ID[6]=0X00;
	ID[7]=0X00;
	

	delay_init();	    	 //延时函数初始化	  
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置中断优先级分组为组2:2位抢占优先级,2位响应优先级
	
	  //初始化ADC1
  ADC1_Init();  
  //启动指定的ADC通道开始AD转换  
  StartADC(); 
	
	uart_init(9600);	 	//串口初始化为9600
	My_USART2_Init(9600);//初始化串口2
	//My_USART3_Init(9600);//初始化串口3
	My_USART4_Init(9600);//初始化串口4
	LED_Init();		  		//初始化与LED连接的硬件接口
  CAN_Mode_Init(CAN_SJW_1tq,CAN_BS2_8tq,CAN_BS1_9tq,4,CAN_Mode_Normal);//CAN初始化正常模式,波特率500Kbps    
	
 	while(1)
	{
		if(Can_Receive_Msg(canbuf))
		{	

		  if(Can_cmp(canbuf,ID))//如果canbuf=ID,进行下面运算
		  {			

				
      arr[0]=SMOKE_buf[0];//蓝光前向
		  arr[1]=SMOKE_buf[1];//蓝光后向
		  arr[2]=SMOKE_buf[2];//红光前向
		  arr[3]=SMOKE_buf[3];//红光后向
			arr[4]=CO_data;//CO浓度(复原时数值乘以2,单位ppm)
			arr[5]=VOC_data;//VOC浓度(复原时数值乘以20,单位mg/m3)
			arr[6]=H2_data;//H2浓度(复原时数值乘以40,单位ppm)
			arr[7]=(u8)HandleADCTemp();//NTC数值(单位摄氏度)
		  Can_Send_Msg(arr,sizeof(arr));
			memset(total_buf,0,sizeof(total_buf));
	    }
	  }

		LED0=0;
		LED1=1;
		delay_ms(500);	 //延时500ms
		LED0=1;
		LED1=0;
		delay_ms(500);	//延时500ms
		}

	}

以上为主要代码,码字不易,给个点赞!下一步就是外壳的3D设计了和3D打印了,这个也很简单,用CAD就可以完成外壳3D设计,生成stl文件后,用嘉立创3D打印下单即可。具体细节敬请期待!

  • 9
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值