```c
```c
/*赛题:第六届:电压测量监控设备
**作者:*wj
**时间:2021-2-15
**注意:设备通过串口发送给PC,思路和LCD动态显示一样(记得添加"stdio.h")
sprintf((char*)time,"%.2f+%.1f+%0.2d%0.2d%0.2d\r\n",ADC_Value, K/10, TH,TM,TS);
*/
**第一部分**
#include "stm32f10x.h"
#include "lcd.h"
#include "stdio.h"
#include "led.h"
#include "key.h"
#include "adc.h"
#include "i2c.h"
#include "rtc.h"
#include "usart.h"
u8 text1[20]; //字符串数组1
u8 RXBUF[20]; //串口接收数组
u8 RXOVER=0; //串口接收标志0:没有接收 1:接收
u8 RXCOUNT=0; //串口数组计数变量
u8 i; //循环变量
u32 TimingDelay = 0; //定时延时变量
u8 TimeDisplay=0; //RTC中断标志变量
float ADC_Value; //采集模拟电压量
float K=1; //参数扩大10倍,方便后面计算保存
u8 Key1_flag = 0; //“B1”按键设定为“功能”按键
u8 Key2_flag = 0; //“B2”按键设定为“设置”按键
u8 Key3_flag = 0; //“B3”切换选择时、分、秒
u8 TH = 00, TM = 00, TS = 00; //定时上报时间变量
u8 LED1_on =0; //LED1闪烁标志位 1:亮 0:灭
u8 LED1_off =0; //LED1闪烁标志位 1:灭 0:亮
//函数的声明
void Delay_Ms(u32 nTime);
void LCD_Init(void);
void LCD_Display(void);
void RCC_Configuration(void);
void Scan_Key(void);
void _24c02_Write(u16 addr,u16 data);
u16 _24c02_Read(u16 addr);
//Main Body
int main(void)
{
i2c_init();
LCD_Init();
RCC_Configuration();
LED_Configuration();
KEY_Configuration();
ADC_Configuration();
RTC_Configuration();
USART2_Configuration();
while(1)
{
Scan_Key();
LCD_Display();
}
}
/***********************LCD_Init函数**************************************/
void LCD_Init(void)
{
STM3210B_LCD_Init();
LCD_Clear(Blue);
LCD_SetBackColor(Blue);
LCD_SetTextColor(White);
SysTick_Config(SystemCoreClock/1000);
K= _24c02_Read(0x01); //上电获取上次断电存储数值
}
/***********************LCD_Display函数**************************************/
void LCD_Display(void)
{
if(RXOVER) //串口接收
{
RXOVER = 0;
if(RXBUF[0] == 'k') //判断接收的内容
{
K = (RXBUF[3] - 48 );
}
Send_String((u8*)"ok\r\n"); //返回给PC机
_24c02_Write(0x01,K); //写入到存储器中
Delay_Ms(10);
for(i=0;i<20;i++) //RXBUF[]数组清零
{
RXBUF[i]=0;
}
USART_ITConfig(USART2,USART_IT_RXNE, ENABLE);
}
if(Key2_flag == 0) //指示灯闪烁报警功能状态和系统时间,
{
ADC_Value = Get_ADC(8) * 3.3 / 0xfff; //电压计算法:ADC采集精度12位,所以是0xfff,电源电压为3.3v
sprintf((char*)text1," V1:%.2f ",ADC_Value);
LCD_DisplayStringLine(Line3,text1);
sprintf((char*)text1," k :%.1f ",K / 10);
LCD_DisplayStringLine(Line4,text1);
if(Key1_flag == 0)
{
LCD_DisplayStringLine(Line5 ," LED: ON ");
}
else if(Key1_flag == 1)
{
LCD_DisplayStringLine(Line5 ," LED: OFF ");
}
Time_Display(RTC_GetCounter()); //时间的获取并且显示
}
if(Key2_flag == 1) //设置界面
{
LCD_DisplayStringLine(Line3 ," Setting ");
switch(Key3_flag )//按键 B3 切换选择时、分、秒
{
case 1: sprintf((char*)text1," %0.2d: ",TH);
LCD_DisplayStringLine(Line5,text1);
break;
case 2: sprintf((char*)text1," %0.2d: ",TM);
LCD_DisplayStringLine(Line5,text1);
break;
case 3: sprintf((char*)text1," %0.2d ",TS);
LCD_DisplayStringLine(Line5,text1);
break;
default:sprintf((char*)text1," %0.2d:%0.2d:%0.2d ",TH,TM,TS);
LCD_DisplayStringLine(Line5,text1);
}
}
//报警显示控制
if(Key1_flag == 0)
{
if((ADC_Value > 3.3 * K / 10)) //当 ADC_Value>VDD*k 时,指示灯 LD1 以 0.2 秒为间隔闪烁
{
if(LED1_on == 1)
{
LED1_on =0;
LED_Control(LED1,0);
}
else if(LED1_off == 1)
{
LED1_off =0;
LED_Control(LED1,1);
}
}
else
{
LED_Control(LED1,1); //否则关闭
}
}
else if(Key1_flag == 1) //闪烁功能可以通过按键关闭
{
LED_Control(LED1,1);
}
}
/************************按键扫描函数**************************************/
void Scan_Key(void)
{
static u8 k4_sum = 0;
if(K1 == 0)
{
Delay_Ms(10);
if(K1 == 0)
{
if(Key1_flag == 0)
{
Key1_flag =1;
}
else
{
Key1_flag =0;
}
}
}
while(K1 == 0);
if(K2 == 0)
{
Delay_Ms(10);
if(K2 == 0)
{
if(Key2_flag == 0)
{
Key2_flag = 1;
}
else
{
Key2_flag = 0;
}
}
}
while(K2 == 0)
{
LCD_ClearLine(Line0);
LCD_ClearLine(Line1);
LCD_ClearLine(Line2);
LCD_ClearLine(Line3);
LCD_ClearLine(Line4);
LCD_ClearLine(Line5);
LCD_ClearLine(Line6);
LCD_ClearLine(Line7);
LCD_ClearLine(Line8);
LCD_ClearLine(Line9);
}
if(K3 == 0)
{
Delay_Ms(10);
if(K3 == 0)
{
if(Key3_flag == 0)
{
Key3_flag = 1;
}
else if(Key3_flag == 1)
{
Key3_flag = 2;
}
else if(Key3_flag == 2)
{
Key3_flag = 3;
}
else
{
Key3_flag = 0;
}
}
}
while(K3 == 0);
if(K4 == 0)
{
k4_sum++;
if(k4_sum == 1) //单次短按
{
if(Key3_flag == 1)
{
if(TH <23)
TH +=1;
else
TH = 0;
}
else if(Key3_flag == 2)
{
if(TM <59)
TM +=1;
else
TM = 0;
}
else if(Key3_flag == 3)
{
if(TS <59)
TS +=1;
else
TS = 0;
}
}
else if(k4_sum == 20) //连续长按
{
if(Key3_flag == 1)
{
if(TH <23)
TH +=1;
else
TH = 0;
}
else if(Key3_flag == 2)
{
if(TM <59)
TM +=1;
else
TM = 0;
}
else if(Key3_flag == 3)
{
if(TS <59)
TS +=1;
else
TS = 0;
}
k4_sum = 15;
}
}
else
{
k4_sum = 0;
}
}
/************************外设时钟函数**************************************/
void RCC_Configuration(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA , ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB , ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC , ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD , ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 , ENABLE);
/* Enable PWR and BKP clocks */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);
/* Enable USART2 clocks */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
}
/***********************_24c02_Write函数**************************************/
/*
入口参数:存储地址(0x00 - 0xff) 存储的内容
*/
void _24c02_Write(u16 addr,u16 data)
{
I2CStart();
I2CSendByte(0xa0);
I2CSendAck();
I2CSendByte(addr);
I2CSendAck();
I2CSendByte(data);
I2CSendAck();
I2CStop();
}
/***********************_24c02_Read函数**************************************/
/*
入口参数:存储地址(0x00 - 0xff)
*/
u16 _24c02_Read(u16 addr)
{
u16 temp;
I2CStart();
I2CSendByte(0xa0);
I2CSendAck();
I2CSendByte(addr);
I2CSendAck();
I2CStart();
I2CSendByte(0xa1);
I2CSendAck();
temp = I2CReceiveByte();
I2CSendAck();
I2CStop();
return temp;
}
//延时函数
void Delay_Ms(u32 nTime)
{
TimingDelay = nTime;
while(TimingDelay != 0);
}
第二部分
#ifndef __USART_H
#define __USART_H
/* Includes ------------------------------------------------------------------*/
#include "stm32f10x.h"
void USART2_Configuration(void);
void Send_String(u8* str);
#endif
#include "usart.h"
void USART2_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
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);
/* Configure USART2 CTS and USART2 Rx as input floating */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
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;
NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
USART_Init(USART2, &USART_InitStructure);
/* Enable the USART2 */
USART_Cmd(USART2, ENABLE);
USART_ITConfig(USART2,USART_IT_RXNE, ENABLE);
}
/**
功能:发送字符串
入口参数:发送内容
**/
void Send_String(u8* str)
{
u8 index=0;
do
{
USART_SendData(USART2,str[index]);
while(USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET);
index++;
}
while(str[index]!= 0);
}
#ifndef __RTC_H
#define __RTC_H
/* Includes ------------------------------------------------------------------*/
#include "stm32f10x.h"
#include "stdio.h"
#include "lcd.h"
#include "usart.h"
#define HH 23
#define MM 59
#define SS 55
void RTC_Configuration(void);
void Time_Display(uint32_t TimeVar);
#endif
#include "rtc.h"
u8 time[20];
extern u8 TH, TM, TS;
extern float ADC_Value;
extern float K;
void RTC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
PWR_BackupAccessCmd(ENABLE);
BKP_DeInit();
/* Enable LSE */
RCC_LSICmd(ENABLE);
/* Wait till LSE is ready */
while (RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == RESET)
{}
/* Select LSE as RTC Clock Source */
RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI);
/* Enable RTC Clock */
RCC_RTCCLKCmd(ENABLE);
/* Wait for RTC registers synchronization */
RTC_WaitForSynchro();
/* Wait until last write operation on RTC registers has finished */
RTC_WaitForLastTask();
/* Enable the RTC Second */
RTC_ITConfig(RTC_IT_SEC, ENABLE);
/* Wait until last write operation on RTC registers has finished */
RTC_WaitForLastTask();
/* Set RTC prescaler: set RTC period to 1sec */
RTC_SetPrescaler(40000-1); /* RTC period = RTCCLK/RTC_PR = (32.768 KHz)/(32767+1) */
/* Wait until last write operation on RTC registers has finished */
RTC_WaitForLastTask();
RTC_SetCounter(HH*3600 + MM*60 + SS);
RTC_WaitForLastTask();
NVIC_InitStructure.NVIC_IRQChannel = RTC_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
void Time_Display(uint32_t TimeVar)
{
uint32_t THH = 0, TMM = 0, TSS = 0;
/* Compute hours */
THH = TimeVar / 3600;
/* Compute minutes */
TMM = (TimeVar % 3600) / 60;
/* Compute seconds */
TSS = (TimeVar % 3600) % 60;
sprintf((char*)time," Time:%0.2d:%0.2d:%0.2d",THH, TMM, TSS);
LCD_DisplayStringLine(Line6 ,time);
//设备自动上报电压时间判断
if(TH == THH)
{
if(TM == TMM)
{
if(TS == TSS)
{
sprintf((char*)time,"%.2f+%.1f+%0.2d%0.2d%0.2d\r\n",ADC_Value, K/10, TH,TM,TS);
Send_String(time);
}
}
}
}
#ifndef __ADC_H
#define __ADC_H
/* Includes ------------------------------------------------------------------*/
#include "stm32f10x.h"
void ADC_Configuration(void);
u16 Get_ADC(u16 channel);
#endif
#include "adc.h"
void ADC_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
ADC_InitTypeDef ADC_InitStructure;
/* Configure PC.04 (ADC Channel14) as analog input -------------------------*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_Init(GPIOB, &GPIO_InitStructure);
/* ADC1 configuration ------------------------------------------------------*/
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;
ADC_Init(ADC1, &ADC_InitStructure);
ADC_Cmd(ADC1, ENABLE);
ADC_ResetCalibration(ADC1);
while(ADC_GetResetCalibrationStatus(ADC1));
ADC_StartCalibration(ADC1);
while(ADC_GetCalibrationStatus(ADC1));
}
/**
功能:获取模拟输入变量
入口参数:ADC的通道(因为板上配置ADC_Channel_8)
局部变量:u16 temp保存读取的模拟量
返回值:temp保存读取的模拟量
**/
u16 Get_ADC(u16 channel)
{
u16 temp;
ADC_RegularChannelConfig(ADC1, channel, 1, ADC_SampleTime_239Cycles5);
ADC_SoftwareStartConvCmd(ADC1, ENABLE);
temp = ADC_GetConversionValue(ADC1);
while(ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC) == 0);
ADC_SoftwareStartConvCmd(ADC1, DISABLE);
return temp;
}
#ifndef __KEY_H
#define __KEY_H
/* Includes ------------------------------------------------------------------*/
#include "stm32f10x.h"
#define K1 GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0)
#define K2 GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_8)
#define K3 GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_1)
#define K4 GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_2)
void KEY_Configuration(void);
#endif
#include "key.h"
void KEY_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_8;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIOB, &GPIO_InitStructure);
}
#ifndef __LED_H
#define __LED_H
/* Includes ------------------------------------------------------------------*/
#include "stm32f10x.h"
#define LED1 GPIO_Pin_8
#define LED2 GPIO_Pin_9
#define LED3 GPIO_Pin_10
#define LED4 GPIO_Pin_11
#define LED5 GPIO_Pin_12
#define LED6 GPIO_Pin_13
#define LED7 GPIO_Pin_14
#define LED8 GPIO_Pin_15
#define LEDALL GPIO_Pin_8|GPIO_Pin_9|GPIO_Pin_10|GPIO_Pin_11|GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15
void LED_Configuration(void);
void LED_Control(u16 ledx,u16 led_sta);
#endif
#include "led.h"
/**
功能:初始化LED管脚
注意:为了防止LCD LED显示的冲突对LCD写函数进行了寄存器的操作
**/
void LED_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = LEDALL;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOC, &GPIO_InitStructure);
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_SetBits(GPIOD,GPIO_Pin_2);
GPIO_SetBits(GPIOC,LEDALL);
GPIO_ResetBits(GPIOD,GPIO_Pin_2);
}
/**
功能:控制LED亮灭
入口参数ledx:LED1-LED8
入口参数led_sta:低电平点亮(根据原理图配置)
**/
void LED_Control(u16 ledx,u16 led_sta)
{
if(led_sta == 0)
{
GPIO_SetBits(GPIOD,GPIO_Pin_2);
GPIO_ResetBits(GPIOC,ledx);
GPIO_ResetBits(GPIOD,GPIO_Pin_2);
}
else
{
GPIO_SetBits(GPIOD,GPIO_Pin_2);
GPIO_SetBits(GPIOC,ledx);
GPIO_ResetBits(GPIOD,GPIO_Pin_2);
}
}