首先我写的代码是参考正点原子的库函数源代码,其形式与正点原子源代码保持一致。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打印下单即可。具体细节敬请期待!