STM32+max6675+hc06实现上位机与下位机分离的水温测量

STM32+max6675+hc06实现上位机与下位机分离的水温测量

本项目设计了一种基于STM32F1单片机的水温测量系统。
该系统由上位机和下位机两部分组成。上位机包括STM32单片机、蓝牙通信模块、LCD显示器和按键等;下位机包括STM32单片机、K型热电偶、MAX6675放大模块、继电器和LCD显示器等。
系统利用搭载MAX6675放大模块的K型热电偶传感器进行水温测量,并通过SPI传输协议将数据传送给下位机中的STM32单片机,并在LCD屏幕上显示。同时,下位机中的STM32单片机通过蓝牙通信模块将水温数据和继电器工作状态传送给上位机中的STM32单片机,并在LCD屏幕上显示。此外,上位机可以通过按键设定上下限温度和恒定温度,并通过蓝牙通信模块传送给下位机中的STM32单片机,以控制下位机中的继电器来控制水温。
实测可以测量水温在0-100范围内,精度在1℃以内。

下位机

下位机主函数

#include "led.h"
#include "delay.h"
#include "key.h"
#include "sys.h"
#include "lcd.h"
#include "usart.h"	 
#include "w25qxx.h"	 

#define N 10


float value_buff[N];                                           //定义算术平均计算缓冲区
float nvalue_buff[N-2];                                        //定义去极值之后的缓冲区

int main(void)	
{	
	extern u8 flag1;
	extern u8 flag2,flag3;
    double t;
	double tp=0;
	double  adcData[10]={0.0};
	float sum;
	int i,major_col,minor_col,j,k;
	double neo;
	double temp;
//	u8 key;
  delay_init();
  max6675_init();
  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置中断优先级分组为组2:2位抢占优先级,2位响应优先级
	uart_init(9600);	 	//串口初始化为115200
	LED_Init();		  		//初始化与LED连接的硬件接口
	LCD_Init();			   	//初始化LCD 	
	KEY_Init();				//按键初始化		 	 	
  while(1)
  {
	  HC06_receive();
	  sum=0;
	  tp=0;
      t = max6675_readTemperature();
      /*这里采用去极值平均滤波*/
	  for(i=0;i<10;i++)
	  {
		  adcData[i]=t;
	  }
	 for(i=0;i<N-1;i++)
	{
		for(j=0;j<N-i-1;j++)
		{
			if(adcData[j]>adcData[j+1])
			{
				temp=adcData[j];
				adcData[j]=adcData[j+1];
				adcData[j+1]=temp;
			}
		}
	}
	for(i=2;i<8;i++)
	{
		tp+=adcData[i];
	}
	/*****************/
		if(tp/6<flag1)
		{
			GPIO_SetBits(GPIOC,GPIO_Pin_0);
			GPIO_ResetBits(GPIOC,GPIO_Pin_1);
		}
		if(tp/6>flag2)
		{
			GPIO_ResetBits(GPIOC,GPIO_Pin_0);
			GPIO_SetBits(GPIOC,GPIO_Pin_1);
		}
		if(flag2-flag1!=2&&tp/6>=flag1+3&&tp/6<=flag2-3)
		{
			GPIO_ResetBits(GPIOC,GPIO_Pin_0);
			GPIO_ResetBits(GPIOC,GPIO_Pin_1);
		}

		LCD_ShowString(10,120,200,16,16,"the temperature is:");
		LCD_ShowFloat(160,120,16,tp/6,3,2);
		LCD_ShowString(10,150,200,16,16,"low temperature  :");
		LCD_ShowNum(160,150,flag1,2,16);
		LCD_ShowString(10,180,200,16,16,"high temperature  :");
		LCD_ShowNum(160,180,flag2,2,16);
		LCD_ShowString(10,210,200,16,16,"set temperature   :");
		LCD_ShowNum(160,210,flag3,2,16);
		
		printf("%lf\r\n",tp/6);
	
        delay_ms(500);
  }
}

下位机max6675放大模块通过SPI和单片机通讯

PA5->SCK
PA6->SO
PA7->SI

#include "spi.h"


/**
  * @brief  硬件spi1初始化
  * @param  None
  * @retval None
  */
void spi1_init(void)
{
 	GPIO_InitTypeDef GPIO_InitStructure;
  SPI_InitTypeDef  SPI_InitStructure;

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

  /* PA5  SPI1_SCK  */
  /* PA6  SPI1_MISO */
  /* PA7  SPI1_MOSI */
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  //PA5/6/7复用推挽输出 SPI
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA

	SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;  //设置SPI单向或者双向的数据模式:SPI设置为双线双向全双工
	SPI_InitStructure.SPI_Mode = SPI_Mode_Master;		//设置SPI工作模式:设置为主SPI
	SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;		//设置SPI的数据大小:SPI发送接收8位帧结构
	SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;		//串行同步时钟的空闲状态为低电平
	SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;	//串行同步时钟的第1个跳变沿(上升或下降)数据被采样
	SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;		//NSS信号由硬件(NSS管脚)还是软件(使用SSI位)管理:内部NSS信号有SSI位控制
	SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_16;		//定义波特率预分频的值:波特率预分频值为256
	SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;	//指定数据传输从MSB位还是LSB位开始:数据传输从MSB位开始
	SPI_InitStructure.SPI_CRCPolynomial = 7;	//CRC值计算的多项式
	SPI_Init(SPI1, &SPI_InitStructure);  //根据SPI_InitStruct中指定的参数初始化外设SPIx寄存器
 
	SPI_Cmd(SPI1, ENABLE); //使能SPI外设

} 

/**
  * @brief  设定spi1的速度
  * @param  SPI_BaudRatePrescaler:分频数 参数如下:
  *             SPI_BaudRatePrescaler_2   2分频   
  *             SPI_BaudRatePrescaler_8   8分频   
  *             SPI_BaudRatePrescaler_16  16分频  
  *             SPI_BaudRatePrescaler_256 256分频 
  * @retval None
  */
void spi1_setSpeed(uint8_t SPI_BaudRatePrescaler)
{
  assert_param(IS_SPI_BAUDRATE_PRESCALER(SPI_BaudRatePrescaler));
	SPI1->CR1&=0XFFC7;
	SPI1->CR1|=SPI_BaudRatePrescaler;	//设置SPI2速度 
	SPI_Cmd(SPI1,ENABLE); 
} 

/**
  * @brief  通过硬件spi1读写一个字节的数据
  * @param  txData:要发送的数据
  * @retval 通过spi接收到的数据
  */
uint8_t spi1_readWriteByte(uint8_t txData)
{		
	uint8_t retry = 0;
  /* Loop while DR register in not emplty */  
	while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET) //检查指定的SPI标志位设置与否:发送缓存空标志位
	{
		retry++;
		if(retry > 200) return 0;
	}			  
	SPI_I2S_SendData(SPI1, txData); //通过外设SPIx发送一个数据( 只有先发送数据才能使能SCK引脚产生时钟)
	
  retry=0;
	while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET) //检查指定的SPI标志位设置与否:接受缓存非空标志位
	{
		retry++;
		if(retry > 200) return 0;
	}	  						    
	return SPI_I2S_ReceiveData(SPI1); //返回通过SPIx最近接收的数据					    
}  

max6675驱动模块代码

#include "MAX6675.h"
#include "spi.h"


/**
  * @brief  max66675模块初始化
  * @param  None
  * @retval None
  */
void max6675_init(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;
  RCC_APB2PeriphClockCmd(MAX6675_CS1_CLK, ENABLE); //PORTA时钟使能 
  
  GPIO_InitStructure.GPIO_Pin = MAX6675_CS1_PIN;  // PA4 推挽 	  T_CS
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;  //推挽输出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
 	GPIO_Init(MAX6675_CS1_PORT, &GPIO_InitStructure);
 	GPIO_SetBits(MAX6675_CS1_PORT,MAX6675_CS1_PIN);	//	T_CS=1
  
  spi1_init();
} 

/**
  * @brief  max6675模块读写一个字节的数据
  * @param  txData:要发送的数据
  * @retval 接收到的数据
  */
uint8_t max6675_readWriteByte(uint8_t txData)
{		
  return spi1_readWriteByte(txData);
}  

/**
  * @brief  max6675模块读取测得的原始数据
  * @param  None
  * @retval 温度的原始数据
  */
uint16_t max6675_readRawValue(void)
{
  uint16_t tmp;
  
  GPIO_ResetBits(MAX6675_CS1_PORT,MAX6675_CS1_PIN); //enable max6675
 
  tmp = max6675_readWriteByte(0XFF); //read MSB
  tmp <<= 8;
  tmp |= max6675_readWriteByte(0XFF); //read LSB
  
  GPIO_SetBits(MAX6675_CS1_PORT,MAX6675_CS1_PIN); //disable max6675
  if (tmp & 4) 
  {
    // thermocouple open
    tmp = 2000; //未检测到热电偶
  }
  else 
  {
    tmp = tmp >> 3;
  }

  return tmp;
}

对max6675模块采集到的数据进行数据分段拟合


/**
  * @brief  对max6675模块做分段拟合
  * @param  None
  * @retval 温度值(单位:℃)
  */
float max6675_readTemperature(void)
{
	double T;
	double temperature;
   temperature = max6675_readRawValue();
  if(0 < temperature && temperature <= 44)
	T = 0.2786*temperature-1.9982;  
	else if(44 < temperature && temperature <= 80)
	T=	0.2713*temperature- 1.7796;
	else if(80 < temperature && temperature <= 121)
	T=	0.2639*temperature - 1.3407;
  else if(121 < temperature && temperature <= 156)
   T=0.29*temperature-4.57;
  else if(156 < temperature && temperature <= 190)
   T=0.29*temperature-6.02;
  else if(190 < temperature && temperature <= 226)
   T=0.27*temperature-2.82;
  else if(226 < temperature && temperature <= 276)
   T=0.20*temperature+14.2;
  else if(276 < temperature && temperature <= 314)
   T=0.24*temperature+4.29;
  else if(314 < temperature && temperature <= 355)
   T=0.2419*temperature +4.0977;
  else if(355 < temperature )
   T=-0.0014*temperature*temperature +1.2583*temperature - 185.93; 
  return(T);
}

下位机蓝牙通讯

这里的flag1代表温度下限,flag2代表温度上限,flag3代表恒定温度。
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include "delay.h" 			 
#include "usart.h" 			 			 
#include "led.h" 
#include "string.h"	 
#include "math.h"
#include "time.h"
// 	 
//如果使用ucos,则包括下面的头文件即可.
#if SYSTEM_SUPPORT_OS
#include "includes.h"					//ucos 使用	  
#endif

u8 flag1=30,flag2=60,flag3=40;

#if 1
#pragma import(__use_no_semihosting)             
//标准库需要的支持函数                 
struct __FILE 
{ 
	int handle; 

}; 

FILE __stdout;       
//定义_sys_exit()以避免使用半主机模式    
void _sys_exit(int x) 
{ 
	x = x; 
} 
//重定义fputc函数 
int fputc(int ch, FILE *f)
{      
	while((USART1->SR&0X40)==0);//循环发送,直到发送完毕   
    USART1->DR = (u8) ch;      
	return ch;
}
#endif 

/*使用microLib的方法*/
 /* 
int fputc(int ch, FILE *f)
{
	USART_SendData(USART1, (uint8_t) ch);

	while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET) {}	
   
    return ch;
}
int GetKey (void)  { 

    while (!(USART1->SR & USART_FLAG_RXNE));

    return ((int)(USART1->DR & 0x1FF));
}
*/
 
#if EN_USART1_RX   //如果使能了接收
//串口1中断服务程序
//注意,读取USARTx->SR能避免莫名其妙的错误   	
u8 USART_RX_BUF[USART_REC_LEN];     //接收缓冲,最大USART_REC_LEN个字节.
//接收状态
//bit15,	接收完成标志
//bit14,	接收到0x0d
//bit13~0,	接收到的有效字节数目
u16 USART_RX_STA=0;       //接收状态标记	  
  
void uart_init(u32 bound){
  //GPIO端口设置
  GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;
	 
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE);	//使能USART1,GPIOA时钟
  
	//USART1_TX   GPIOA.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);//初始化GPIOA.9
   
  //USART1_RX	  GPIOA.10初始化
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//PA10
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
  GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.10  

  //Usart1 NVIC 配置
  NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;//抢占优先级3
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;		//子优先级3
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			//IRQ通道使能
	NVIC_Init(&NVIC_InitStructure);	//根据指定的参数初始化VIC寄存器
  
   //USART 初始化设置

	USART_InitStructure.USART_BaudRate = bound;//串口波特率
	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_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启串口接受中断
  USART_Cmd(USART1, ENABLE);                    //使能串口1 

}

void HC06_receive(void)                 //接收函数 
{  
	u8 reclen=0;
	if(USART_RX_STA&0X8000)			//接收到一次数据了
		{
			
 			reclen=USART_RX_STA&0X7FFF;	//得到数据长度
		  	USART_RX_BUF[reclen]=0;	 	//加入结束符


				if(strcmp(USART_RX_BUF,"1")==0&&flag1<=flag2)//舵机1开闭
				{	
					flag1+=5;
					printf("flag1\r\n");
				}
				if(strcmp(USART_RX_BUF,"2")==0&&flag1<flag2) //继电器开
				{	
					flag1-=5;
					printf("flag2\r\n");     
				}
				if(strcmp(USART_RX_BUF,"3")==0&&flag1<=flag2)//继电器关,舵机2开闭
				{	    
					flag2+=5;
					printf("flag3\r\n");
				}
				if(strcmp(USART_RX_BUF,"4")==0&&flag1<=flag2)//继电器关,舵机2开闭
				{	
					flag2-=5;
					printf("flag4\r\n");
				}
				
				if(strcmp(USART_RX_BUF,"5")==0&&flag1<=flag2)//继电器关,舵机2开闭
				{	
					flag3+=1;
					flag1=flag3-1;
					flag2=flag3+1;
					printf("flag5\r\n");
//					printf("jidianqi4\r\n");
				}
				if(strcmp(USART_RX_BUF,"6")==0&&flag1<=flag2)//继电器关,舵机2开闭
				{	
					flag3-=1;
					flag1=flag3-1;
					flag2=flag3+1;
					printf("flag6\r\n");
//					printf("jidianqi4\r\n");
				}
				if(flag1>flag2)
				{
					flag1-=10;
					printf("flag1\r\n");
				}

 			USART_RX_STA=0;	 
		}	 															     
}

void USART1_IRQHandler(void)                	//串口1中断服务程序
	{
	u8 Res;
#if SYSTEM_SUPPORT_OS 		//如果SYSTEM_SUPPORT_OS为真,则需要支持OS.
	OSIntEnter();    
#endif
	if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)  //接收中断(接收到的数据必须是0x0d 0x0a结尾)
		{
		Res =USART_ReceiveData(USART1);	//读取接收到的数据
		
		if((USART_RX_STA&0x8000)==0)//接收未完成
			{
			if(USART_RX_STA&0x4000)//接收到了0x0d
				{
				if(Res!=0x0a)USART_RX_STA=0;//接收错误,重新开始
				else USART_RX_STA|=0x8000;	//接收完成了 
				}
			else //还没收到0X0D
				{	
				if(Res==0x0d)USART_RX_STA|=0x4000;
				else
					{
					USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ;
					USART_RX_STA++;
					if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;//接收数据错误,重新开始接收	  
					}		 
				}
			}   		 
     } 
#if SYSTEM_SUPPORT_OS 	//如果SYSTEM_SUPPORT_OS为真,则需要支持OS.
	OSIntExit();  											 
#endif
} 
#endif	

上位机

上位机主函数

这里采用6个按键对上下限温度与恒定温度进行设置
#include "led.h"
#include "delay.h"
#include "key.h"
#include "sys.h"
#include "usart.h"
#include "lcd.h"

 int main(void)
 {		
		extern u8 flag1;
	extern u8 flag2,flag3; 
	vu8 key=0;	 	
	delay_init();	    	 //延时函数初始化	  
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
	uart_init(9600);	 //串口初始化为9600
 	LED_Init();			     //LED端口初始化
	KEY_Init();          //初始化与按键连接的硬件接口
	LCD_Init();

	LCD_ShowString(10,60,200,16,16,"the temperature is:");
	LCD_ShowString(10,90,200,16,16,"low temperature  :");
	LCD_ShowString(10,120,200,16,16,"high temperature  :");
	LCD_ShowString(10,150,200,16,16,"set temperature   :");
 
 while(1)
	{
		HC06_receive();
 		key=KEY_Scan(0);	//得到键值
	   	if(key)
		{						   
			switch(key)
			{				 
				case KEY0_PRES:	
					printf("1\r\n");
					
					break;
				case KEY1_PRES:
					printf("2\r\n");
					
					break;
				case KEY2_PRES:	
					printf("3\r\n");
					break;
				case KEY3_PRES:	
					printf("4\r\n");
					
					break;
				case KEY4_PRES:	
					printf("5\r\n");				
					break;
				case KEY5_PRES:	
					printf("6\r\n");
					break; 
			}
		} 
	}	 
 }

上位机蓝牙通讯

#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include "delay.h" 			 
#include "usart.h" 			 			 
#include "led.h" 
#include "string.h"	 
#include "math.h"
#include "time.h"
#include "lcd.h"
// 	 
//如果使用ucos,则包括下面的头文件即可.
#if SYSTEM_SUPPORT_OS
#include "includes.h"					//ucos 使用	  
#endif

u8 flag1=30,flag2=60,flag3=40;

#if 1
#pragma import(__use_no_semihosting)             
//标准库需要的支持函数                 
struct __FILE 
{ 
	int handle; 

}; 

FILE __stdout;       
//定义_sys_exit()以避免使用半主机模式    
void _sys_exit(int x) 
{ 
	x = x; 
} 
//重定义fputc函数 
int fputc(int ch, FILE *f)
{      
	while((USART1->SR&0X40)==0);//循环发送,直到发送完毕   
    USART1->DR = (u8) ch;      
	return ch;
}
#endif 

 
#if EN_USART1_RX   //如果使能了接收
//串口1中断服务程序
//注意,读取USARTx->SR能避免莫名其妙的错误   	
u8 USART_RX_BUF[USART_REC_LEN];     //接收缓冲,最大USART_REC_LEN个字节.
//接收状态
//bit15,	接收完成标志
//bit14,	接收到0x0d
//bit13~0,	接收到的有效字节数目
u16 USART_RX_STA=0;       //接收状态标记	  
  
void uart_init(u32 bound){
  //GPIO端口设置
  GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;
	 
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE);	//使能USART1,GPIOA时钟
  
	//USART1_TX   GPIOA.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);//初始化GPIOA.9
   
  //USART1_RX	  GPIOA.10初始化
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//PA10
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
  GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.10  

  //Usart1 NVIC 配置
  NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;//抢占优先级3
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;		//子优先级3
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			//IRQ通道使能
	NVIC_Init(&NVIC_InitStructure);	//根据指定的参数初始化VIC寄存器
  
   //USART 初始化设置

	USART_InitStructure.USART_BaudRate = bound;//串口波特率
	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_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启串口接受中断
  USART_Cmd(USART1, ENABLE);                    //使能串口1 

}

void HC06_receive(void)                 //接收函数 
{  
	u8 reclen=0;
	double t;
	if(USART_RX_STA&0X8000)			//接收到一次数据了
	{
		
		reclen=USART_RX_STA&0X7FFF;	//得到数据长度
		USART_RX_BUF[reclen]=0;	 	//加入结束符

		if(strcmp(USART_RX_BUF,"flag1")==0&&flag1<=flag2)
		{
			flag1+=5;
		}
		else if(strcmp(USART_RX_BUF,"flag2")==0&&flag1<=flag2)
		{
			flag1-=5;
		}
		else if(strcmp(USART_RX_BUF,"flag3")==0&&flag1<=flag2)
		{
			flag2+=5;
		}
		else if(strcmp(USART_RX_BUF,"flag4")==0&&flag1<=flag2)
		{
			flag2-=5;
		}
		else if(strcmp(USART_RX_BUF,"flag5")==0&&flag1<=flag2)
		{
			flag3+=1;
			flag1=flag3-1;
			flag2=flag3+1;
		}
		else if(strcmp(USART_RX_BUF,"flag6")==0&&flag1<=flag2)
		{
			flag3-=1;
			flag1=flag3-1;
			flag2=flag3+1;
		}
		else if(flag1>flag2)
		{
			flag1-=10;	
		}
		else
		{	
			t=strtod(USART_RX_BUF,NULL);
			LCD_ShowFloat(160,60,16,t,3,2);
			LCD_ShowNum(160,90,flag1,2,16);
			LCD_ShowNum(160,120,flag2,2,16);
			LCD_ShowNum(160,150,flag3,2,16);
			
			if(t<flag1)
			{
				LCD_ShowString(10,180,200,16,16,"heating   ");
			}
			if(t>flag2)
			{
				LCD_ShowString(10,180,200,16,16,"cooling   ");
			}
			if(flag2-flag1!=2&&t>=flag1+3&&t<=flag2-3)
			{
				LCD_ShowString(10,180,200,16,16,"no working");
			}
		}			
		USART_RX_STA=0;	 
		}
	
}

void USART1_IRQHandler(void)                	//串口1中断服务程序
	{
	u8 Res;
#if SYSTEM_SUPPORT_OS 		//如果SYSTEM_SUPPORT_OS为真,则需要支持OS.
	OSIntEnter();    
#endif
	if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)  //接收中断(接收到的数据必须是0x0d 0x0a结尾)
		{
		Res =USART_ReceiveData(USART1);	//读取接收到的数据
		
		if((USART_RX_STA&0x8000)==0)//接收未完成
			{
			if(USART_RX_STA&0x4000)//接收到了0x0d
				{
				if(Res!=0x0a)USART_RX_STA=0;//接收错误,重新开始
				else USART_RX_STA|=0x8000;	//接收完成了 
				}
			else //还没收到0X0D
				{	
				if(Res==0x0d)USART_RX_STA|=0x4000;
				else
					{
					USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ;
					USART_RX_STA++;
					if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;//接收数据错误,重新开始接收	  
					}		 
				}
			}   		 
     } 
#if SYSTEM_SUPPORT_OS 	//如果SYSTEM_SUPPORT_OS为真,则需要支持OS.
	OSIntExit();  											 
#endif
} 
#endif	
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: MFC是一种Microsoft Foundation Class的缩写,是Microsoft Windows操作系统的一种应用框架,使用C++语言进行开发。STM32是一种基于ARM Cortex-M内核的32位微控制器系列,主要用于嵌入式系统开发。 在MFC上位机STM32下位机通讯中,通常采用串口通信的方式进行数据传输。首先,在MFC上位机开发环境中,需要通过串口编程来实现STM32下位机的通信。先设置好串口的参数,如波特率、数据位数、校验位等,然后通过打开串口来建立与下位机的连接。 在STM32下位机端,通过配置串口的参数与MFC上位机进行通信。首先需要设置串口的波特率、数据位数、校验位等与上位机相匹配,然后通过发送和接收数据的函数来完成通信。STM32下位机可以通过串口发送数据给上位机上位机通过读取串口缓冲区的数据来接收下位机发送的数据。同样地,上位机可以通过串口发送数据给下位机下位机会通过读取串口缓冲区的数据来接收上位机发送的数据。 在通信的过程中,可以通过制定一些协议来实现数据的可靠传输和解析。例如,可以定义一种通信协议,包括数据包的格式、起始标志、数据长度、校验位等信息,以确保数据的准确传输和解析。 总结起来,MFC上位机STM32下位机通信主要通过串口进行数据传输,并需要在上位机下位机中分别进行串口的设置和数据的发送、接收。合理地设计和实现通信协议可以确保数据的可靠传输和解析。 ### 回答2: MFC(Microsoft Foundation Class)是在Windows操作系统下开发图形用户界面的一个框架。而STM32是一种基于ARM Cortex-M内核的微控制器,用于嵌入式系统开发。 MFC上位机STM32下位机通讯是指通过串口或其他通讯接口,实现MFC应用程序与STM32芯片之间的数据交互。 首先,需要在STM32上编写代码,配置相关的通讯接口(如USART)和通讯协议(如UART、SPI或I2C)。STM32负责接收和发送数据,可以将接收到的数据进行处理,并通过特定的协议将数据发送给MFC。 接下来,在MFC应用程序中,需要使用相关的类库或API来实现STM32通讯。MFC提供了用于串口通讯的类(如CSerialPort),可以用于打开和配置串口,读取和发送数据。 在MFC应用程序中,需要先打开与STM32的通讯接口,设置相关的通讯参数(如波特率、数据位、停止位等),然后就可以使用类库提供的方法来读取从STM32接收到的数据,或是向STM32发送数据。 通过MFC应用程序与STM32下位机的通讯,可以实现许多功能。例如,在MFC界面上显示STM32传感器采集到的数据,通过MFC应用程序向STM32发送指令控制其执行特定的操作,或是实现远程监控和控制等。 总结起来,MFC上位机STM32下位机通讯是通过串口或其他通讯接口实现数据的双向传输,需要在STM32上配置通讯接口和协议,并在MFC应用程序中使用类库或API进行通讯。这种通讯方式在嵌入式系统开发和物联网应用中非常常见,具有广泛的应用价值。 ### 回答3: MFC上位机STM32下位机通讯是指通过MFC(Microsoft Foundation Classes)框架开发的上位机与通过STM32单片机搭建的下位机之间的数据交互和通信。 在MFC上位机中,我们可以使用串口通信来与STM32下位机进行通讯。首先,我们需要在MFC应用程序中配置串口通信参数,包括波特率、数据位、停止位和校验位等。然后,通过打开串口,可以与已连接的STM32下位机进行数据的收发。 在STM32下位机上,我们需要对串口进行初始化设置,包括串口的硬件参数和中断的使能。通过配置串口的相关寄存器,可以实现串口的数据收发功能。下位机可以通过中断的方式来接收和处理MFC上位机发送过来的数据,并通过串口发送数据给上位机。 在数据通信过程中,需要定义一套协议来约定上位机下位机之间的数据格式。例如,可以定义一段特定的起始标志位,然后跟上数据内容和校验位等信息。上位机发送数据时,需要遵循协议的定义格式,下位机则需要进行解析和处理收到的数据。 此外,MFC上位机还可以通过其他通信方式如USB、以太网等与STM32下位机进行通讯。不同的通信方式需要使用不同的硬件设备和相应的通信协议。 总结来说,MFC上位机STM32下位机通讯需要通过串口等通信方式来进行数据的收发和处理,并通过定义的协议来确保通信的准确性和稳定性。这种通信方式在物联网、嵌入式系统等领域广泛应用,在实际项目开发中需要根据具体需求进行配置和开发。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

GH_pursue

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值