1 题目分析
使用到的外设:LED、LCD、按键、串口、ADC、I2C。
2 Cubemx配置
外设具体方法参考我写的其他文章
配置完成如下:
时钟树配置如下:
3 文件移植
其中灯和按键程序自己添加
添加到项目中
先编译,左边会显示出添加的文件
添加头文后再编译一下,确保头文件和.c文件都被正确引用
4 代码
所有的外设配置Cubemx都配置好了,无需自己配置(巨省工作量)
下面介绍自己添加的部分
4.1 led和Key部分
头文件 ledAndKey.h
#include "main.h"
void Led_Disp(unsigned char c);
unsigned char Key_Scan(void);
.c文件
#include "ledAndKey.h"
//灯
void Led_Disp(unsigned char c)
{
//全部熄灭
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15|GPIO_PIN_8
|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET);
//点亮对应位
HAL_GPIO_WritePin(GPIOC, c<<8, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET);
}
//按键扫描
unsigned char Key_Scan(void)
{
unsigned char c;
if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0)==GPIO_PIN_RESET)
{
c = 1;
}
else if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1)==GPIO_PIN_RESET)
{
c = 2;
}
else if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_2)==GPIO_PIN_RESET)
{
c = 3;
}
else if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0)==GPIO_PIN_RESET)
{
c = 4;
}
return c;
}
4.2 ADC部分
ADC文件最后添加两个函数
int GetADC1_R38(void);
int GetADC2_R37(void);
int GetADC1_R38(void)
{
int a;
HAL_ADC_Start(&hadc2);
a = HAL_ADC_GetValue(&hadc2);
return a;
}
int GetADC2_R37(void)
{
int a;
HAL_ADC_Start(&hadc1);
a = HAL_ADC_GetValue(&hadc1);
return a;
}
4.3 i2c部分
添加读和写两个函数
void i2cWrite(unsigned char *p,unsigned char addr,unsigned char num);
void i2cRead(unsigned char *p,unsigned char addr,unsigned char num);
void i2cWrite(unsigned char *p,unsigned char addr,unsigned char num)
{
I2CStart();
I2CSendByte(0xa0);
I2CWaitAck();
I2CSendByte(addr);
I2CWaitAck();
while(num--)
{
I2CSendByte(*p++);
I2CWaitAck();
}
I2CStop();
delay1(500);
}
void i2cRead(unsigned char *p,unsigned char addr,unsigned char num)
{
I2CStart();
I2CSendByte(0xa0);
I2CWaitAck();
I2CSendByte(addr);
I2CWaitAck();
I2CStart();
I2CSendByte(0xa1);
I2CWaitAck();
while(num--)
{
*p++ = I2CReceiveByte();
if(num)
I2CSendAck();
else
I2CSendNotAck();
}
I2CStop();
}
4.4 主函数部分
#include "main.h"
#include "adc.h"
#include "usart.h"
#include "gpio.h"
#include "ledAndKey.h"
#include <stdio.h>
#include "i2c - hal.h"
#include "lcd.h"
void SystemClock_Config(void);
void keyPro(void);
void lcdPro(void);
void ledPro(void);
void ADCPro(void);
//dida
__IO uint32_t uwtick_Key,uwtick_Lcd,uwtick_Led,uwtick_ADC,uwtick_rx_it;
//key
unsigned char Key_Value,Key_Old,Key_Up,Key_Dowm;
//adc
double ADCR37,ADCR38;
double adc_value[3]; //滤波器太长会有延迟,是否是题中所述?
double adc_value1;
unsigned char adc_index = 1;
//led
unsigned char LED_Value;
unsigned char Led_index = 0;
unsigned char Led2_flag = 0;
unsigned char Led3_flag = 0;
//user
unsigned char page = 1;
unsigned char str[20];
unsigned char uart_rx_it[1];
//unsigned char uart_rx[5];
char uart_tx[20];
unsigned char high;
unsigned char level = 0;
unsigned char level_old = 0;
unsigned char set_L1 = 30;
unsigned char set_L2 = 50;
unsigned char set_L3 = 70;
unsigned char set_L11;
unsigned char set_L22;
unsigned char set_L33;
unsigned char i2ctxbuf[3];
unsigned char i2crxbuf[3];
unsigned char set_num = 0; //设置参数选择
int main(void)
{
HAL_Init();
SystemClock_Config();
LCD_Init();
MX_GPIO_Init();
MX_ADC1_Init();
MX_ADC2_Init();
MX_USART1_UART_Init();
I2CInit();
HAL_UART_Receive_IT(&huart1,uart_rx_it,1);
LCD_Clear(Blue);
LCD_SetBackColor(Blue);
LCD_SetTextColor(White);
ADCR38 = GetADC1_R38()*3.3/4096;
for(int i = 0;i<3;i++) //均值滤波初始化
{
adc_value[i] = ADCR38;
}
// i2ctxbuf[0] = set_L1;
// i2ctxbuf[1] = set_L2;
// i2ctxbuf[2] = set_L3;
//
// i2cWrite(i2ctxbuf,0,3);
// HAL_Delay(10);
i2cRead(i2crxbuf,0,3);
set_L1 = i2crxbuf[0];
set_L2 = i2crxbuf[1];
set_L3 = i2crxbuf[2];
while (1)
{
keyPro();
ADCPro();
ledPro();
lcdPro();
}
}
//lcd显示
void lcdPro(void)
{
if(uwTick - uwtick_Lcd<50) return;
uwtick_Lcd = uwTick;
if(page == 1)
{
sprintf((char *)str," Liquid Level");
LCD_DisplayStringLine(Line1,str);
sprintf((char *)str," Height: %d",high);
LCD_DisplayStringLine(Line3,str);
sprintf((char *)str," ADC: %4.2f",adc_value1);
LCD_DisplayStringLine(Line5,str);
sprintf((char *)str," Level: %d",level);
LCD_DisplayStringLine(Line7,str);
}
else //
{
sprintf((char *)str," Parameter Setup");
LCD_DisplayStringLine(Line1,str);
if(set_num == 0)
{
sprintf((char *)str," Threshold 1: %02d",set_L1);
LCD_DisplayStringLine(Line3,str);
sprintf((char *)str," Threshold 2: %02d",set_L2);
LCD_DisplayStringLine(Line5,str);
sprintf((char *)str," Threshold 3: %02d",set_L3);
LCD_DisplayStringLine(Line7,str);
}
else
{
if(set_num == 1)
{
LCD_SetTextColor(Green);
}
else
{
LCD_SetTextColor(White);
}
sprintf((char *)str," Threshold 1: %02d",set_L11);
LCD_DisplayStringLine(Line3,str);
if(set_num == 2)
{
LCD_SetTextColor(Green);
}
else
{
LCD_SetTextColor(White);
}
sprintf((char *)str," Threshold 2: %02d",set_L22);
LCD_DisplayStringLine(Line5,str);
if(set_num == 3)
{
LCD_SetTextColor(Green);
}
else
{
LCD_SetTextColor(White);
}
sprintf((char *)str," Threshold 3: %02d",set_L33);
LCD_DisplayStringLine(Line7,str);
LCD_SetTextColor(White);
}
}
}
void keyPro(void)
{
if(uwTick - uwtick_Key<50) return;
uwtick_Key = uwTick;
Key_Value = Key_Scan();
Key_Dowm = Key_Value&(Key_Value^Key_Old);
Key_Up = ~Key_Value&(Key_Value^Key_Old);
Key_Old = Key_Value;
if(Key_Dowm == 1) //页面切换
{
LCD_Clear(Blue);
if(page == 1)
{
page = 2;
set_L11 = set_L1;
set_L22 = set_L2;
set_L33 = set_L3;
}
else
{
page = 1;
set_L1 = set_L11;
set_L2 = set_L22;
set_L3 = set_L33;
//保存
i2ctxbuf[0] = set_L1;
i2ctxbuf[1] = set_L2;
i2ctxbuf[2] = set_L3;
i2cWrite(i2ctxbuf,0,3);
}
}
else if(Key_Dowm == 2)
{
if(page==2)
{
set_num++;
if(set_num>3)
set_num = 1;
}
else
{
set_num = 0;
}
}
else if(Key_Dowm == 3)
{
if(set_num == 1)
{
set_L11+=5;
if(set_L11>=set_L22)
set_L11 = set_L22;
if(set_L11>=95)
set_L11 = 95;
}
else if(set_num == 2)
{
set_L22+=5;
if(set_L22>=set_L33)
set_L22 = set_L33;
if(set_L22>=95)
set_L22 = 95;
}
else if(set_num == 3)
{
set_L33+=5;
if(set_L33>=95)
set_L33 = 95;
}
}
else if(Key_Dowm == 4)
{
if(set_num == 1)
{
set_L11-=5;
if(set_L11<=5)
set_L11 = 5;
}
else if(set_num == 2)
{
set_L22-=5;
if(set_L22<=set_L11)
set_L22 = set_L11;
if(set_L22<=5)
set_L22 = 5;
}
else if(set_num == 3)
{
set_L33-=5;
if(set_L33<=set_L22)
set_L33= set_L22;
if(set_L33<=5)
set_L33 = 5;
}
}
}
void ledPro(void)
{
if(uwTick - uwtick_Led<200) return;
uwtick_Led = uwTick;
Led_index++;
if(Led2_flag != 0)
{
LED_Value^=0x2;
Led2_flag++;
if(Led2_flag > 10)
Led2_flag = 0;
}
if(Led3_flag != 0)
{
LED_Value^=0x4;
Led3_flag++;
if(Led3_flag > 10)
Led3_flag = 0;
}
if(Led_index == 5)
{
LED_Value^=0x1;
Led_index = 0;
}
Led_Disp(LED_Value);
}
void ADCPro(void)
{
if(uwTick - uwtick_ADC<100) return;
uwtick_ADC = uwTick;
ADCR38 = GetADC1_R38()*3.3/4096;
ADCR37 = GetADC2_R37()*3.3/4096;
//更新队列
int index = 1;
while(index<=2)
{
adc_value[adc_index - 1] = adc_value[adc_index];
index++;
}
adc_value[2] = ADCR38;
adc_index++;
if(adc_index > 10)
adc_index = 1;
if(adc_index == 1) //1s算一次
{
adc_value1 = 0;
for(int k = 0;k<3;k++)
{
adc_value1+=adc_value[k];
}
adc_value1 = adc_value1/3;
high = adc_value1*100/3.3;
}
if(high<=set_L1)
{
level = 0;
}
else if(high<=set_L2)
{
level = 1;
}
else if(high<=set_L3)
{
level = 2;
}
else
{
level = 3;
}
if(level != level_old) //液位等级变化
{
Led2_flag = 1;
if(level>level_old)
sprintf(uart_tx,"A:H%02d+L%d+U\r\n",high,level);
else
sprintf(uart_tx,"A:H%02d+L%d+D\r\n",high,level);
HAL_UART_Transmit(&huart1,(unsigned char *)uart_tx,strlen(uart_tx),50);
}
level_old = level;
}
//接受中断
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if(uart_rx_it[0] == 'C')
{
Led3_flag = 1;
sprintf(uart_tx,"C:H%02d+L%d\r\n",high,level);
HAL_UART_Transmit(&huart1,(unsigned char *)uart_tx,strlen(uart_tx),50);
}
else if(uart_rx_it[0] == 'S')
{
Led3_flag = 1;
sprintf(uart_tx,"S:TL%02d+TM%02d+TH%02d\r\n",set_L1,set_L2,set_L3);
HAL_UART_Transmit(&huart1,(unsigned char *)uart_tx,strlen(uart_tx),50);
}
HAL_UART_Receive_IT(&huart1,uart_rx_it,1);
}