使用到的外设:LED、LCD、按键、串口、TIM(PWM)。
外设具体方法参考我写的其他文章
配置完成如下:
时钟树配置如下:
其中灯和按键程序自己添加
添加到项目中
先编译,左边会显示出添加的文件
添加头文后再编译一下,确保头文件和.c文件都被正确引用
所有的外设配置Cubemx都配置好了,无需自己配置(巨省工作量)
下面介绍自己添加的部分
头文件 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;
}
#include "main.h"
#include "tim.h"
#include "usart.h"
#include "gpio.h"
#include "ledAndKey.h"
#include
#include "lcd.h"
void SystemClock_Config(void);
void keyPro(void);
void lcdPro(void);
void ledPro(void);
//dida
__IO uint32_t uwtick_Key,uwtick_Lcd,uwtick_Led,uwtick_rx_it;
//key
unsigned char Key_Value,Key_Old,Key_Up,Key_Dowm;
//led
unsigned char LED_Value;
//uart
unsigned char str[20];
unsigned char uart_rx_it[1];
unsigned char uart_rx[25];
unsigned char uart_tx[25];
unsigned char uart_index = 0;
unsigned char car[8][1+22];//8辆车的信息 空闲标志
unsigned char car_flag = 0; //查询车牌索引
//user
unsigned char CNBR = 0;
unsigned char VNBR = 0;
unsigned char IDLE = 8;
double free_CNBR = 3.5;
double free_VNBR = 2;
unsigned char page = 1;
unsigned char pwm_flag = 0;
unsigned char time;
double free;
unsigned char error_flag;
int main(void)
{
HAL_Init();
SystemClock_Config();
LCD_Init();
MX_GPIO_Init();
MX_TIM17_Init();
MX_USART1_UART_Init();
HAL_UART_Receive_IT(&huart1,uart_rx_it,1);
HAL_TIM_PWM_Start(&htim17,TIM_CHANNEL_1);
__HAL_TIM_SET_COMPARE(&htim17,TIM_CHANNEL_1,0);
LCD_Clear(Black);
LCD_SetBackColor(Black);
LCD_SetTextColor(White);
Led_Disp(0);
while (1)
{
keyPro();
lcdPro();
ledPro();
}
}
void lcdPro(void)
{
if(uwTick - uwtick_Lcd<50) return;
uwtick_Lcd = uwTick;
if(page == 1)
{
sprintf((char *)str," DATA ");
LCD_DisplayStringLine(Line1,str);
sprintf((char *)str," CNBR:%d ",CNBR);
LCD_DisplayStringLine(Line3,str);
sprintf((char *)str," VNBR:%d ",VNBR);
LCD_DisplayStringLine(Line5,str);
sprintf((char *)str," IDLE:%d ",IDLE);
LCD_DisplayStringLine(Line7,str);
}
else
{
sprintf((char *)str," PARA ");
LCD_DisplayStringLine(Line1,str);
sprintf((char *)str," CNBR:%4.2f ",free_CNBR);
LCD_DisplayStringLine(Line3,str);
sprintf((char *)str," VNBR:%4.2f ",free_VNBR);
LCD_DisplayStringLine(Line5,str);
}
sprintf((char *)str,"%d ",uart_index);
LCD_DisplayStringLine(Line8,str);
sprintf((char *)str,"TEST ");
LCD_DisplayStringLine(Line9,str);
}
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(Black);
if(page == 1)
{
page = 2;
}
else
{
page = 1;
}
}
else if(Key_Dowm == 2)
{
if(page == 2)
{
free_CNBR += 0.5;
free_VNBR += 0.5;
}
}
else if(Key_Dowm == 3)
{
if(page == 2)
{
if(free_CNBR>=0.5)
{
free_CNBR -= 0.5;
}
else
{
free_CNBR = 0;
}
if(free_VNBR>=0.5)
{
free_VNBR -= 0.5;
}
else
{
free_VNBR = 0;
}
}
}
else if(Key_Dowm == 4)
{
if(pwm_flag == 0)
{
pwm_flag = 1;
}
else
{
pwm_flag = 0;
}
}
}
void ledPro(void)
{
if(uwTick - uwtick_Led<100) return;
uwtick_Led = uwTick;
LED_Value = 0;
if(pwm_flag == 0)
{
__HAL_TIM_SET_COMPARE(&htim17,TIM_CHANNEL_1,0);
LED_Value&=0xfd;
}
else
{
__HAL_TIM_SET_COMPARE(&htim17,TIM_CHANNEL_1,100);
LED_Value|=0x2;
}
//Led_Disp(LED_Value);
//接受超时
if(uwTick - uwtick_rx_it > 200)
{
if((error_flag == 1||uart_index<22)&&uart_index!=0)
{
sprintf((char *)uart_tx,"Error\r\n");
HAL_UART_Transmit(&huart1,uart_tx,strlen((char *)uart_tx),50);
}
uart_index = 0;
}
}
//接受中断
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if((uart_rx_it[0] == 'V'||uart_rx_it[0] == 'C')&&uart_index == 0)
{
uart_index = 1; //数据头有效 ,开始接受后面的数据
uart_rx[0] = uart_rx_it[0];
uwtick_rx_it = uwTick;//开始计时
}
else if(uart_index != 0)
{
uart_rx[uart_index] = uart_rx_it[0];
uart_index++;
if(uart_index >= 22) //到达数据尾,解析数据
{
if(uart_rx[9] == ':'&&uart_rx[4]==':') //有效数据
{
car_flag = 0;
//对比车牌信息
for(int i = 0;i<8;i++)
{
if(car[i][0]!=0)//此i坑有车
{
if(uart_rx[0]==car[i][1]&&uart_rx[5]==car[i][6]&&uart_rx[6]==car[i][7]&&uart_rx[7]==car[i][8]&&uart_rx[8]==car[i][9]) //车牌一样
{
car_flag = i; //坑位值赋给car_flag
}
}
}
//判断执行
if(car_flag == 0&&IDLE != 0) //说明没车匹配,且有空位,进场
{
for(int j = 0;j<8;j++)
{
if(car[j][0]==0&&car_flag == 0)//找到第一个空位
{
car_flag = j; //第j个
}
}
//存数据
car[car_flag][0] = 1; //标志位
for(int k = 0;k<22;k++)
{
car[car_flag][k+1] = uart_rx[k]; //存入时间
}
if(car[car_flag][1] == 'C')
CNBR ++;
else
VNBR++;
IDLE--;
}
else //出场(数组第car_flag个)
{
car[car_flag][0] = 0;//清除标志位
//计算费用
time = uart_rx[16]*10+uart_rx[17]-car[car_flag][17]*10-car[car_flag][18];//小时
if(uart_rx[18]*10+uart_rx[19] - car[car_flag][19]*10-car[car_flag][20]>0) //判断分
{
time+=1;
}
else
{
if(uart_rx[20]*10+uart_rx[21] - car[car_flag][21]*10-car[car_flag][22]>0)
{
time+=1;
}
}
if(car[car_flag][1] == 'C')
free = time*free_CNBR;
else
free = time*free_VNBR;
sprintf((char *)uart_tx,"%cNBR:%c%c%c%c:%02d:%5.2f\r\n",car[car_flag][1],car[car_flag][6],car[car_flag][7],car[car_flag][8],car[car_flag][9],time,free);
HAL_UART_Transmit(&huart1,uart_tx,strlen((char *)uart_tx),50);
if(car[car_flag][1] == 'C')
CNBR --;
else
VNBR--;
IDLE++;
}
}
else //数据有误
{
uart_index = 0;
error_flag = 1;
}
}
}
HAL_UART_Receive_IT(&huart1,uart_rx_it,1);
}
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
/** Configure the main internal regulator output voltage
*/
HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1);
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = RCC_PLLM_DIV3;
RCC_OscInitStruct.PLL.PLLN = 20;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2;
RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
{
Error_Handler();
}
/** Initializes the peripherals clocks
*/
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_RTC|RCC_PERIPHCLK_USART1;
PeriphClkInit.Usart1ClockSelection = RCC_USART1CLKSOURCE_PCLK2;
PeriphClkInit.RTCClockSelection = RCC_RTCCLKSOURCE_HSE_DIV32;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
{
Error_Handler();
}
}