蓝桥杯嵌入式国赛 ---- 第十届试题解析


前言

**本程序设计是基于嵌入式开发板CT117E,stm32f103RBT6。

如果对哪个模块的代码不理解可以点开我的博客查看各个模块的编写思路。


一、试题

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

二、需要用到的模块

1.LED

代码如下:led.c:

#include "led.h"

void led_init(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD | RCC_APB2Periph_GPIOC, ENABLE);

  /* Configure PD0 and PD2 in output pushpull mode */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  GPIO_Init(GPIOD, &GPIO_InitStructure);

   GPIO_InitStructure.GPIO_Pin = 0xff00;
   GPIO_Init(GPIOC, &GPIO_InitStructure);
   GPIOC->ODR |=0xff<<8;
   GPIOD->ODR |=1<<2;
   GPIOD->ODR &=~(1<<2);
}

void led_ctrl(u8 ledx,u8 status)   //控制led的亮灭,ledx取值范围:8-15
{
	if(status)
	{
		GPIOC->ODR &=~(1<<ledx);    
   		GPIOD->ODR |=1<<2;
   		GPIOD->ODR &=~(1<<2);	
	}
	else
	{
	  	GPIOC->ODR |=1<<ledx;
   		GPIOD->ODR |=1<<2;
   		GPIOD->ODR &=~(1<<2);
	}
}

led.h:

#ifndef LED_H
#define LED_H

#include "stm32f10x.h"

void led_init(void);
void led_ctrl(u8 ledx,u8 status);
#endif

2.按键

代码如下:key.c:

#include "key.h"

void key_init(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB, ENABLE);

  /* Configure PD0 and PD2 in output pushpull mode */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_8;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  GPIO_Init(GPIOA, &GPIO_InitStructure);

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2;
  GPIO_Init(GPIOB, &GPIO_InitStructure);

}

key.h:

#include "key.h"

#ifndef KEY_H
#define KEY_H

#include "stm32f10x.h"

#define key1 GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0)   //读取按键的状态
#define key2 GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_8)
#define key3 GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_1)
#define key4 GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_8)

void key_init(void);
#endif

3.ADC

代码如下:adc.c:

#include "adc.h"

void adc_init(void)
{
  ADC_InitTypeDef ADC_InitStructure;
  GPIO_InitTypeDef GPIO_InitStructure;

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOA, ENABLE);

  /* Configure PC.01, PC.02 and PC.04 (ADC Channel11, Channel12 and Channel14)
    as analog input ----------------------------------------------------------*/
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_4;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
  GPIO_Init(GPIOA, &GPIO_InitStructure);

  /* ADC1 configuration ------------------------------------------------------*/
  ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
  ADC_InitStructure.ADC_ScanConvMode = ENABLE;
  ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
  ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
  ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
  ADC_InitStructure.ADC_NbrOfChannel = 1;
  ADC_Init(ADC1, &ADC_InitStructure);
  /* ADC1 regular channels configuration */ 
  //ADC_RegularChannelConfig(ADC1, ADC_Channel_4, 1, ADC_SampleTime_239Cycles5);  
  
  ADC_Cmd(ADC1, ENABLE);

  /* Enable ADC1 reset calibration register */   
  ADC_ResetCalibration(ADC1);
  /* Check the end of ADC1 reset calibration register */
  while(ADC_GetResetCalibrationStatus(ADC1));

  /* Start ADC1 calibration */
  ADC_StartCalibration(ADC1);
  /* Check the end of ADC1 calibration */
  while(ADC_GetCalibrationStatus(ADC1));  
}

u16 get_adc(u8 Channel)
{
	u8 i,j;
	u16 t[50];
	ADC_SoftwareStartConvCmd(ADC1, ENABLE);
	ADC_RegularChannelConfig(ADC1, Channel, 1, ADC_SampleTime_239Cycles5);
	for(i=0;i<50;i++)
	{
		t[i]=ADC_GetConversionValue (ADC1);
	}
	ADC_SoftwareStartConvCmd(ADC1, DISABLE);
	for(i=0;i<50-1;i++)
	{
		for(j=0;j<50-1-i;j++)
		{
			if(t[j]>t[j+1])
			{
				t[j]=t[j] ^ t[j+1];
				t[j+1]=t[j] ^ t[j+1];
				t[j]=t[j] ^ t[j+1];
			}
		}
	}
	return (t[24]+t[25])/2;
}

}


adc.h:

#ifndef ADC_H
#define ADC_H

#include "stm32f10x.h"

void adc_init(void);
u16 get_adc(void);

#endif

4.定时器3捕获PWM2

代码如下:capture.c:

#include "capture.h"
u8 ch2_mode=0  ;
void time3_capture_init(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
	TIM_ICInitTypeDef  TIM_ICInitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;
		/* TIM3 clock enable */
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);

  /* GPIOA clock enable */
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);

  /* Enable the TIM3 global Interrupt */
  NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);


  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7 ;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;

  GPIO_Init(GPIOA, &GPIO_InitStructure);


  /* Time base configuration */
  TIM_TimeBaseStructure.TIM_Period = 65535;
  TIM_TimeBaseStructure.TIM_Prescaler = 71;
  TIM_TimeBaseStructure.TIM_ClockDivision = 0;
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;

  TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);

  
  TIM_ICInitStructure.TIM_Channel = TIM_Channel_2;
  TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
  TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
  TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
  TIM_ICInitStructure.TIM_ICFilter = 0x0;

  TIM_ICInit(TIM3, &TIM_ICInitStructure);
  
  /* TIM enable counter */
  TIM_Cmd(TIM3, ENABLE);

  /* Enable the CC2 Interrupt Request */
  TIM_ITConfig(TIM3, TIM_IT_CC2, ENABLE);
}
u32 ch2_val,ch2_duty;

void TIM3_IRQHandler(void)
{ 
  if(TIM_GetITStatus(TIM3, TIM_IT_CC2) == SET) 
  {
    /* Clear TIM3 Capture compare interrupt pending bit */
    TIM_ClearITPendingBit(TIM3, TIM_IT_CC2);
    switch(ch2_mode)
	{
		case 0: ch2_val=0;
				ch2_duty=0;
				TIM_SetCounter(TIM3,0); 
				TIM_OC2PolarityConfig(TIM3,TIM_OCPolarity_Low);
				ch2_mode=1;
				break;

		case 1: ch2_duty=TIM_GetCounter(TIM3);
				TIM_OC2PolarityConfig(TIM3,TIM_OCPolarity_High);
				ch2_mode=2;
			    break;

		case 2: ch2_val=TIM_GetCounter(TIM3);
				TIM_OC2PolarityConfig(TIM3,TIM_OCPolarity_High);
				ch2_mode=3;
				break;

		default: break;
	}
  }
}


capture.h:

#ifndef CAPTURE_H
#define CAPTURE_H
#include "stm32f10x.h"

extern 	 u8 ch2_mode;
extern 	u32 ch2_val,ch2_duty;

void time3_capture_init(void);

#endif

5.ds18b20测量温度

代码如下:ds18b20.c:


#include "stm32f10x.h"
#include "ds18b20.h"

#define delay_us(X)  delay((X)*72/5)

void delay(unsigned int n)
{
	while(n--);
}

void ds18b20_init_x(void)
{
  	GPIO_InitTypeDef GPIO_InitStructure;
  	/* Enable  clock */
  	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA  , ENABLE);
  
  	/* Configure Ports */
  	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
  	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
  	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
  	GPIO_Init(GPIOA, &GPIO_InitStructure);
}

//
void mode_input1(void )
{
  	GPIO_InitTypeDef GPIO_InitStructure;

  	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
  	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
  	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
  	GPIO_Init(GPIOA, &GPIO_InitStructure);
}

void mode_output1(void )
{
  	GPIO_InitTypeDef GPIO_InitStructure;

  	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
  	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
  	GPIO_Init(GPIOA, &GPIO_InitStructure);
}

//
uint8_t ow_reset(void)
{ 
	uint8_t err;

   	OW_DIR_OUT(); // pull OW-Pin low for 480us
   	OW_OUT_LOW(); // disable internal pull-up (maybe on from parasite)

   	delay_us(400);	  //about 480us
   
   	// set Pin as input - wait for clients to pull low
   	OW_DIR_IN(); // input

   	delay_us(66);
   	err = OW_GET_IN();		// no presence detect
   	// nobody pulled to low, still high


   	// after a delay the clients should release the line
  	// and input-pin gets back to high due to pull-up-resistor
   	delay_us(480-66);
   	if( OW_GET_IN() == 0 )		// short circuit
      err = 1;

   	return err;
 }

uint8_t ow_bit_io( uint8_t b )
{ 
 	OW_DIR_OUT(); // drive bus low
 	OW_OUT_LOW();	
 	delay_us(1); // Recovery-Time wuffwuff was 1

 	if ( b ) OW_DIR_IN(); // if bit is 1 set bus high (by ext. pull-up)
	
#define  OW_CONF_DELAYOFFSET  5
 	delay_us(15-1-OW_CONF_DELAYOFFSET);
      
 	if( OW_GET_IN() == 0 ) b = 0;  // sample at end of read-timeslot
	
 	delay_us(60-15);
 	OW_DIR_IN();

 	return b;
}

uint8_t ow_byte_wr( uint8_t b )
{ 	
	uint8_t i = 8, j;
   	do 
    { 
		j = ow_bit_io( b & 1 );
      	b >>= 1;
      	if( j ) b |= 0x80;
    } 
   	while( --i );
   	return b;
}

//
uint8_t ow_byte_rd( void )
{
   	return ow_byte_wr( 0xFF ); 
}
float ds18b20_read(void)
{
	u8 i;
	s16 x;
	u8 val[2];
	u8 s;
	float temp;
	

	ow_reset();
	ow_byte_wr(OW_SKIP_ROM);
	ow_byte_wr(DS18B20_CONVERT);
	//delay_us(750000);

	ow_reset();
	ow_byte_wr(OW_SKIP_ROM);
	ow_byte_wr(DS18B20_READ);

	for(i=0;i<2;i++)
	{
		val[i]=ow_byte_rd();
	}

	if(val[1]>7)
	{
		val[0]=~val[0];
		val[1]=~val[1];
		s=1;
	}
	else
	{
		s=0;
	}

	x=val[1];
	x=x<<8;
	x=x | val[0];
	//x=x&0x7ff;
	temp=(float)x/16.0;

	if(s)
	{
		return -temp;
	}
	else
	{
		return temp;
	}


}


ds18b20.h:

#ifndef __DS18B20_H
#define __DS18B20_H

#include "stm32f10x.h"

#define OW_DIR_OUT() 	mode_output1()
#define OW_DIR_IN() 	mode_input1()
#define OW_OUT_LOW() 	(GPIO_ResetBits(GPIOA,GPIO_Pin_6))
#define OW_GET_IN()  	(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_6))

#define OW_SKIP_ROM 		0xCC
#define DS18B20_CONVERT 	0x44
#define DS18B20_READ 		0xBE


void ds18b20_init_x(void);
float ds18b20_read(void);

#endif


6.i2c对eeprom的存取

i2c.c

/*
  程序说明: CT117E嵌入式竞赛板GPIO模拟I2C总线驱动程序
  软件环境: Keil uVision 4.10 
  硬件环境: CT117E嵌入式竞赛板
  日    期: 2011-8-9
*/

#include "stm32f10x.h"
#include "i2c.h"
/** I2C 总线接口 */
#define I2C_PORT GPIOB
#define SDA_Pin	GPIO_Pin_7
#define SCL_Pin GPIO_Pin_6

#define FAILURE 0
#define SUCCESS 1

//配置SDA信号线为输入模式
void SDA_Input_Mode()
{
	GPIO_InitTypeDef GPIO_InitStructure;

	GPIO_InitStructure.GPIO_Pin = SDA_Pin;
  	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
  	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;	 

  	GPIO_Init(I2C_PORT, &GPIO_InitStructure);
}

//配置SDA信号线为输出模式
void SDA_Output_Mode()
{
	GPIO_InitTypeDef GPIO_InitStructure;

	GPIO_InitStructure.GPIO_Pin = SDA_Pin;
  	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
  	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;

  	GPIO_Init(I2C_PORT, &GPIO_InitStructure);
}

//
void SDA_Output( uint16_t val )
{
	if ( val ) {
		GPIO_SetBits(I2C_PORT,SDA_Pin);
	} else {
		GPIO_ResetBits(I2C_PORT,SDA_Pin);
	}
}

//
void SCL_Output( uint16_t val )
{
	if ( val ) {
		GPIO_SetBits(I2C_PORT,SCL_Pin);
	} else {
		GPIO_ResetBits(I2C_PORT,SCL_Pin);
	}
}

//
uint8_t SDA_Input()
{
	return GPIO_ReadInputDataBit( I2C_PORT, SDA_Pin);
}

//延时程序
void delay1(unsigned int n)
{
	unsigned int i;
	for ( i=0;i<n;++i);
}

//I2C总线启动
void I2CStart(void)
{
	SDA_Output(1);delay1(500);
	SCL_Output(1);delay1(500);
	SDA_Output(0);delay1(500);
	SCL_Output(0);delay1(500);
}

//I2C总线停止
void I2CStop(void)
{
	SCL_Output(0); delay1(500);
	SDA_Output(0); delay1(500);
	SCL_Output(1); delay1(500);
	SDA_Output(1); delay1(500);

}

//等待应答
unsigned char I2CWaitAck(void)
{
	unsigned short cErrTime = 5;
	SDA_Input_Mode(); 
	delay1(500);
	SCL_Output(1);delay1(500);
	while(SDA_Input())
	{
		cErrTime--;
		delay1(500);
		if (0 == cErrTime)
		{
			SDA_Output_Mode();
			I2CStop();
			return FAILURE;
		}
	}
	SDA_Output_Mode();
	SCL_Output(0);delay1(500); 
	return SUCCESS;
}

//发送应答位
void I2CSendAck(void)
{
	SDA_Output(0);delay1(500);
	delay1(500);
	SCL_Output(1); delay1(500);
	SCL_Output(0); delay1(500);

}

//
void I2CSendNotAck(void)
{
	SDA_Output(1);
	delay1(500);
	SCL_Output(1); delay1(500);
	SCL_Output(0); delay1(500);

}

//通过I2C总线发送一个字节数据
void I2CSendByte(unsigned char cSendByte)
{
	unsigned char  i = 8;
	while (i--)
	{
		SCL_Output(0);delay1(500); 
		SDA_Output(cSendByte & 0x80); delay1(500);
		cSendByte += cSendByte;
		delay1(500); 
		SCL_Output(1);delay1(500); 
	}
	SCL_Output(0);delay1(500); 
}

//从I2C总线接收一个字节数据
unsigned char I2CReceiveByte(void)
{
	unsigned char i = 8;
	unsigned char cR_Byte = 0;
	SDA_Input_Mode(); 
	while (i--)
	{
		cR_Byte += cR_Byte;
		SCL_Output(0);delay1(500); 
		delay1(500); 
		SCL_Output(1);delay1(500); 
		cR_Byte |=  SDA_Input(); 
	}
	SCL_Output(0);delay1(500); 
	SDA_Output_Mode();
	return cR_Byte;
}

//I2C总线初始化
void i2c_init()
{
	GPIO_InitTypeDef GPIO_InitStructure;

	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);

	GPIO_InitStructure.GPIO_Pin = SDA_Pin | SCL_Pin;
  	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
  	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;	 // **

  	GPIO_Init(I2C_PORT, &GPIO_InitStructure);

}

void i2c_write(u8 addr,u8 data)
{
	I2CStart();

	I2CSendByte(0xa0);
	I2CWaitAck();

	I2CSendByte(addr);
	I2CWaitAck();

	I2CSendByte(data);
	I2CWaitAck();

	I2CStop();
}

u8 i2c_read(u8 addr)
{
	u8 t;
	I2CStart();

	I2CSendByte(0xa0);
	I2CWaitAck();

	I2CSendByte(addr);
	I2CWaitAck();

	I2CStart();
	I2CSendByte(0xa1);
	I2CWaitAck();
	
	t=I2CReceiveByte();
	I2CWaitAck();
	I2CStop();

	return t;
}

i2c.h

#ifndef  __I2C_H__
#define  __I2C_H__

void i2c_init(void);
void delay1(unsigned int n);

void I2CStart(void);
void I2CStop(void);
void I2CSendAck(void);
void I2CSendNotAck(void);
unsigned char I2CWaitAck(void);

void I2CSendByte(unsigned char cSendByte);
unsigned char I2CReceiveByte(void);
void i2c_write(u8 addr,u8 data);
u8 i2c_read(u8 addr);

#endif

7.数码管显示

seg.c

#include "seg.h"
u8 table[17] = { 0x3f,0x06,0x5b,0x4f, 0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c, 0x39,0x4f,0x79,0x78,0x00};
void seg_init(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;
  /* GPIOD Periph clock enable */
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

  /* Configure PD0 and PD2 in output pushpull mode */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_1 | GPIO_Pin_3;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  GPIO_Init(GPIOA, &GPIO_InitStructure);

}

void seg_show(u8 bit1,u8 bit2, u8 bit3)
{
	u8 bit;
	u8 i;
	RCK_L;	  // 锁住数据,防止串口的干扰,使得 RCK为高电平, 造成数码管显示错误
	bit=table[bit3];
	for(i=0;i<8;i++)
	{
		if(bit&0x80)
		{
			SER_H;
		}
		else
		{
			SER_L;
		}
		
		SCK_H;
		bit=bit<<1;
		SCK_L;
	}

	bit=table[bit2];
	for(i=0;i<8;i++)
	{
		if(bit&0x80)
		{
			SER_H;
		}
		else
		{
			SER_L;
		}
		
		SCK_H;
		bit=bit<<1;
		SCK_L;
	}

	bit=table[bit1];
	for(i=0;i<8;i++)
	{
		if(bit&0x80)
		{
			SER_H;
		}
		else
		{
			SER_L;
		}
		
		SCK_H;
		bit=bit<<1;
		SCK_L;
	}

	RCK_H;	   //等到所有数据都移位成功后,再一次性将移位寄存器的数据存放到数据寄存器进行数码管显示

}

seg.h

#ifndef SEG_H
#define SEG_H
#include "stm32f10x.h"

#define SER_H GPIO_SetBits(GPIOA,GPIO_Pin_1)
#define SER_L GPIO_ResetBits(GPIOA,GPIO_Pin_1)

#define RCK_H GPIO_SetBits(GPIOA,GPIO_Pin_2)
#define RCK_L GPIO_ResetBits(GPIOA,GPIO_Pin_2)

#define SCK_H GPIO_SetBits(GPIOA,GPIO_Pin_3)
#define SCK_L GPIO_ResetBits(GPIOA,GPIO_Pin_3)

void seg_init(void);
void seg_show(u8 bit1,u8 bit2, u8 bit3);
#endif

8.串口

usart.c

#include "usart.h"
void usart_init(void)
{
	NVIC_InitTypeDef NVIC_InitStructure;
	USART_InitTypeDef USART_InitStructure;
	GPIO_InitTypeDef GPIO_InitStructure;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA| RCC_APB2Periph_AFIO, ENABLE);
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE); 
	
	
  /* Configure USARTy Rx as input floating */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  GPIO_Init(GPIOA, &GPIO_InitStructure);
   
  
  /* Configure USARTy Tx as alternate function push-pull */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  GPIO_Init(GPIOA, &GPIO_InitStructure);

	USART_InitStructure.USART_BaudRate = 9600;
  USART_InitStructure.USART_WordLength = USART_WordLength_8b;
  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;

  /* Configure USARTz */
  USART_Init(USART2, &USART_InitStructure);
  /* Enable USARTz Receive and Transmit interrupts */
  USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);
  /* Enable the USARTz */
  USART_Cmd(USART2, ENABLE);
	
  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
	  /* Enable the USARTz Interrupt */
  NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);
}
void sent_data(char *s)
{
	do
	{
		USART_SendData(USART2,*s++);
		while(USART_GetFlagStatus(USART2,USART_FLAG_TXE)==0);
	}while(*s);
}



u8 usart_buff[8];
u8 count=0;
u8 data, para,erro;
void USART2_IRQHandler(void)
{
  if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET)
  {
	 usart_buff[count]=USART_ReceiveData(USART2);
	 if(usart_buff[0]=='S' && usart_buff[1]=='T' )
	 {
	 	data=1;
	 } 

	 if(usart_buff[0]=='P' && usart_buff[1]=='A' && usart_buff[2]=='R' && usart_buff[3]=='A' )
	 {
	 	para=1;
	 }
	 else 
	 {
	 	erro=1;
	 }

	 count++;
	  
  	
  }
}

usart.h

#ifndef USART_H
#define USART_H
#include "stm32f10x.h"
void usart_init(void);
void sent_data(char *s);
extern u8 data, para,count,erro;
extern u8 usart_buff[8];


#endif


三、主函数逻辑设计

stm32f10x_it.c:

#include "stm32f10x_it.h"
#include "usart.h"
extern u32 TimingDelay;
extern u8 key_flag;
extern u8 adc_flag;
extern u8 seg_flag;
extern u8 led_flag;
extern u8 usart_flag;

void SysTick_Handler(void)
{
	static u8 key_num=0;
	static u16 adc_num=0;
	static u16 seg_num=0;
	static u16 usart_num=0;
	static u8 led_num=0;
	key_num++;

	if(key_num==50)
	{
		key_flag=1;
		key_num=0;
	}
	
	adc_num++;
	if(adc_num==300)
	{
		adc_flag=1;
		adc_num=0;
	}

	seg_num++;
	if(seg_num==2000)
	{
		seg_flag ^=1;
		seg_num=0;
	}
	usart_num++;
	if(usart_num==1000)
	{
		usart_flag ^=1;
		usart_num=0;
	}

	led_num++;
	if(led_num==200)
	{
		led_flag ^=1;
		led_num=0;
	}
	TimingDelay--;
}

这里串口和数码管的引脚冲突,需要分时复用。
main.c:

#include "stm32f10x.h"
#include "stdio.h"
#include "lcd.h"
#include "led.h"
#include "key.h"
#include "adc.h"
#include "capture.h"
#include "ds18b20.h"
#include "seg.h"
#include "i2c.h"
#include "usart.h"

u32 TimingDelay = 0;
u8 key_flag;	  //按键消抖标志,每50ms刷新一次
u8 adc_flag;	  //adc收集刷新标志300ms
u8 key1_num;	  //按键按下的递增值,用于判断长按和短按
u8 key2_num;
u8 key3_num;
u8 key4_num;
u16 adc_val;	 //存放16位的adc值
u8 key1_flag=1;	  //按键1按下的标志
u8 buff[20];	  //存放拷贝数据缓冲区
u8 led_flag;	  //led灯的刷新标志,200ms
u8 usart_flag;	  //串口的刷新标志位,1000ms
float temp;		  //存放ds18b20的温度值
float v[2];		  //存放两路ADC电压的值
u8 t=30;			 //存放设置参数T的值
u8 x=1;				 //存放AO1,AO2的值
u8 x_temp,t_temp;	 //用于存放之前的下,t,x的值,用来判断数据是否被更新
u16 n=0;			  //存放设置的次数
u8 i;				 //用于for循环
u8 seg_flag;		 //数码管的刷新标志位,2000ms
u8 key2_flag=1;		  //按键2按下的标志位
void Delay_Ms(u32 nTime);
void key_read(void);
void lcd_show(void);
void seg_fun(void);			//数码管处理函数
void usart_fun(void);		//串口接收后的处理和函数
int main(void)
{
	SysTick_Config(SystemCoreClock/1000);

	Delay_Ms(200);
	
	STM3210B_LCD_Init();
	LCD_Clear(Blue);
	LCD_SetBackColor(Blue);
	LCD_SetTextColor(Black);

	led_init();
	key_init();
	adc_init();
	time3_capture_init();
	ds18b20_init_x();
//	seg_init();
    i2c_init();
//	usart_init();
	//sent_data("123\n\r");
	if(i2c_read(0x20)!=58)
	{
		led_ctrl(15,1);
		i2c_write(0x20,58);
		Delay_Ms(5);
		i2c_write(0x25,n);
		Delay_Ms(5);
	}
	n=i2c_read(0x25);
	Delay_Ms(5);
	
	while(1)
	{
		if(key_flag)
		{
			key_read();
			key_flag=0;
		}

		if(temp>t)
		{
			led_ctrl(15,led_flag);	
		}
		else
		{
			led_ctrl(15,0);
		}


		if(v[x-1]>((float)ch2_duty/ch2_val)*3.3 && usart_flag==1)
		{
			led_ctrl(8,1);
			sprintf((char *)buff,"$%0.2f\r\n",temp);
			sent_data((char *)buff);
			usart_flag=0;
		}
		else
		{
			led_ctrl(8,0);
		}

		lcd_show();
		usart_fun();
		Delay_Ms(5);
		seg_fun();

		

		
		

	}
}


void Delay_Ms(u32 nTime)
{
	TimingDelay = nTime;
	while(TimingDelay != 0);	
}


void key_read(void)
{
	if(key1==0)
	{
		key1_num++;
		if(key1_num>15)
		{
			
		}
	}
	else
	{
		if(key1_num>1 && key1_num<8)
		{
			key1_flag ^= 1;
			if(key1_flag==0)
			{
				x_temp=x;
				t_temp=t;
			}
			else
			{
				if(x_temp!=x || t_temp!=t)
				{
					n++;
					i2c_write(0x25,n);
		            Delay_Ms(5);
				}
			}
		}
		key1_num=0;
	}
//


	if(key2==0 && key1_flag==0)
	{
		key2_num++;
		if(key2_num>15)
		{
		
		}
	}
	else
	{
		if(key2_num>1 && key2_num<8)
		{
			key2_flag ^=1;
		}
		key2_num=0;
	}
//

	if(key3==0 && key1_flag==0 )
	{
		key3_num++;
		if(key3_num>15)
		{
		   if(key2_flag==1)
		   {
		   		t++;
				if(t>40)
				{
					t=40;
				}
		   }
		}
	}
	else
	{
		if(key3_num>1 && key3_num<8)
		{
		   if(key2_flag==1)
		   {
		   		t++;
				if(t>40)
				{
					t=40;
				}
		   }
		   else
		   {
		   	  if(x==1)
			  {
			  	x=2;
			  }
			  else
			  {
			  	x=1;
			  }
		   }
		}
		key3_num=0;
	}
//
	if(key4==0 && key1_flag==0)
	{
		key4_num++;
		if(key4_num>15)
		{
			if(key2_flag==1)
		   {
		   		t--;
				if(t<20)
				{
					t=20;
				}
		   }
		}
	}
	else
	{
		if(key4_num>1 && key4_num<8)
		{
		  if(key2_flag==1)
		   {
		   		t--;
				if(t<20)
				{
					t=20;
				}
		   }
		   else
		   {
		   	  if(x==1)
			  {
			  	x=2;
			  }
			  else
			  {
			  	x=1;
			  }
		   }
		}
		key4_num=0;
	}
}			  

void lcd_show(void)
{
	if(key1_flag)
	{
		LCD_DisplayStringLine(Line1,"       Main         ");
		if(adc_flag)
		{
			adc_val=get_adc(ADC_Channel_4);
			v[0]=(float)adc_val*3.3/0xfff;
			sprintf((char *)buff," AO1:%0.2fV           ",v[0]);
			LCD_DisplayStringLine(Line3,buff);
			
			adc_val=get_adc(ADC_Channel_5);
			v[1]=(float)adc_val*3.3/0xfff;
			sprintf((char *)buff," AO2:%0.2fV           ",v[1]);
			LCD_DisplayStringLine(Line4,buff);	
			adc_flag=0;
		}
		
		if(ch2_mode==3)
		{
			sprintf((char *)buff," PWM2:%d%%           ",ch2_duty*100/ch2_val);
			LCD_DisplayStringLine(Line5,buff);
			ch2_mode=0;	
		}
		
		temp=ds18b20_read();
		sprintf((char *)buff," Temp:%0.2fC           ",temp);
		LCD_DisplayStringLine(Line6,buff);
		
		sprintf((char *)buff," N:%d                 ",n);
		LCD_DisplayStringLine(Line7,buff);	
	}
	else
	{
		 LCD_SetBackColor(Blue);	
		 LCD_DisplayStringLine(Line1,"       Para         ");
		 if(key2_flag==1)
		 {
		 	LCD_SetBackColor(Yellow);
		 }
		 else
		 {
		 	LCD_SetBackColor(Blue);		 	
		 }
		 sprintf((char *)buff," T:%d                      ",t);
		 LCD_DisplayStringLine(Line3,buff);
		 if(key2_flag==0)
		 {
		 	LCD_SetBackColor(Yellow);
		 }
		 else
		 {
		 	LCD_SetBackColor(Blue);		 	
		 }
		 sprintf((char *)buff," X:AO%d                 ",x);
	     LCD_DisplayStringLine(Line4,buff);
		 LCD_SetBackColor(Blue);	
		 LCD_DisplayStringLine(Line5,"                        ");
		 LCD_DisplayStringLine(Line6,"                        ");
		 LCD_DisplayStringLine(Line7,"                        ");
	}
}

void seg_fun(void)
{
	seg_init();
	if(seg_flag)
	{
	  seg_show(12,t/10,t%10);
	}
	else
	{
	  seg_show(10,0,x);
	}								
	usart_init();	
}
void usart_fun(void)
{

	if(data)
	{
		sprintf((char *)buff,"$%0.2f\r\n",temp);
		sent_data((char *)buff);
		data=0;
		count=0;

		for(i=0;i<8;i++)
		{
			usart_buff[i]=0;
		}
	}
	if(para)
	{
		para=0;
		count=0;
		sprintf((char *)buff,"#%d,AO%d\r\n",t,x);
		sent_data((char *)buff);
		for(i=0;i<8;i++)
		{
			usart_buff[i]=0;
		}
		
	}
	if(erro)
	{
		count=0;
		for(i=0;i<8;i++)
		{
			usart_buff[i]=0;
		}
		erro=0;
	}
	seg_fun();
	
}

四、 代码测试结果图

①主测试界面:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

②设置界面

在这里插入图片描述
在这里插入图片描述

  • 1
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值