本文最后更新于 34 天前,其中的信息可能已经有所发展或是发生改变。
初始化
点亮LCD
首先要添加三个文件到工程下,需要新建一个文件夹。
然后将新建的文件夹目录添加到路径
然后根据原理图设置io口
#include "lcd.h"
LCD_Init();
LCD_Clear(Black);
LCD_SetBackColor(Black);
LCD_SetTextColor(White);
//初始化代码
//将字符串赋值给text然后通过display函数显示在lcd上,第一个参数是行,第二个参数是要显示的内容,需要转为uint8_t 指针类型
char text[20];
sprintf(text," Para");
LCD_DisplayStringLine(Line1,(uint8_t *)text);
sprintf(text," CNBR:%.2f",cnbrbite);
LCD_DisplayStringLine(Line3,(uint8_t *)text);
按键
dsp文件下新建key.c和.h文件
cubmx文件下四个io口设置为input
然后我们要在中断里处理key
如图可以进行1ms中断设置
HAL_TIM_Base_Start_IT(&htim1);
仅单击检测
#ifndef _KEY_H_
#define _KEY_H_
#include "main.h"
#include "stdbool.h"
struct key
{
bool state;
int casenum;
int setflag;
};
#endif
#include "key.h"
struct key keys[4];
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
//读取io口电平
if(htim->Instance==TIM1)
{
keys[0].state=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0);
keys[1].state=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1);
keys[2].state=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_2);
keys[3].state=HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0);
}
//io口电平处理
for(int i=0;i<4;i++)
{
switch(keys[i].casenum)
{
//case 0 用来检测电平是否有变化,如果有就将casenum+1
case 0:
{
if(keys[i].state==0)
{
keys[i].casenum=1;
}
}
break;
//case 1 用来检测电平是否真的被按下,如果有则casenum+1,如果只是虚假的按下(电平波动造成)casenum-1
case 1:
{
if(keys[i].state==0)
{
keys[i].casenum=2;
}
else
{
keys[i].casenum=0;
}
}
break;
//用来设置按下的标志位,在main文件中读取keys[i].setjud是否为1就可以判断是否被按下
case 2:
{
if(keys[i].state==1)
{
keys[i].setflag=1;
keys[i].casenum=0;
}
}
break;
}
}
}
if(keys[0].setflag==1)
{
//do something
//检测完记得清零标志位
keys[0].setflag=0;
}
单击、长按检测
#ifndef _KEY_H
#define _KEY_H_
#include "main.h"
#include "stdbool.h"
struct key
{
bool state;
int setflag;
int casenum;
int uptime;
};
#endif
#include "key.h"
struct key keys[4];
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
//读取
if(htim->Instance==TIM1)
{
keys[0].state=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0);
keys[1].state=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1);
keys[2].state=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_2);
keys[3].state=HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0);
}
//识别
for(int i=0;i<4;i++)
{
switch (keys[i].casenum)
{
case 0:
{
if(keys[i].state==0)
{
keys[i].casenum=1;
}
}break;
case 1:
{
if(keys[i].state==0)
{
keys[i].casenum=2;
}
else
{
keys[i].casenum=0;
}
}break;
case 2:
{
keys[i].uptime++;
if(keys[i].state==1)
{
keys[i].casenum=0;
keys[i].setflag=1;
if(keys[i].uptime>2000)
{
keys[i].setflag=2;
}
keys[i].uptime=0;
}
}
}
}
}
单击、双击、长按检测
#ifndef _KEY_H
#define _KEY_H
#include "main.h"
struct key
{
int setflag;
int state;
int casenum;
int double_detection_time;
int short_long_detection_time;
/* data */
};
#endif
#include "key.h"
struct key keys[4];
//setflag 1为短2为长3为双击
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if(htim->Instance==TIM3)
{
keys[1].state=HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0);
keys[2].state=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1);
keys[3].state=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_2);
keys[4].state=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_3);
}
for(int i=0;i<4;i++)
{
if(keys[i].setflag==1)
{
keys[i].double_detection_time++;
}
switch (keys[i].casenum)
{
case 0:
if(keys[i].state==0)
{
keys[i].casenum=1;
}
break;
case 1:
if(keys[i].state==0)
{
keys[i].short_long_detection_time++;
if(keys[i].state==1)
{
keys[i].casenum=2;
}
}
else keys[i].casenum=0;
break;
case 2:
{
if(keys[i].short_long_detection_time<500)
{
if(keys[i].double_detection_time<500&&keys[i].setflag==1)
{
keys[i].setflag=3;
keys[i].double_detection_time=0;
}
else
{
keys[i].setflag=1;
keys[i].double_detection_time=0;
}
}
else
{
keys[i].setflag=2;
keys[i].double_detection_time=0;
}
keys[i].casenum=0;
keys[i].timeuse=0;
}
break;
}
}
}
LED
照着原理图设置,记得别忘了PD2,因为它通过pd来控制锁存器
#ifndef _LED_H_
#define _LED_H_
#include "main.h"
void LED_set(int num);
void LED_off(int num);
#endif
#include "led.h"
int led=0x00;
void led_set(int num)
{
led|=num;
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_All,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOC,led<<8,GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);
}
void led_clear(int num)
{
led&=~num;
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_All,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOC,led<<8,GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);
}
if(keys[0].setflag==1)
{
led_set(0x01);
}
if(keys[1].setflag==1)
{
led_set(0x02);
}
if(keys[2].setflag==1)
{
led_set(0x04);
}
if(keys[3].setflag==1)
{
led_clear(0x01);
}
串口通信
使用中断或者dma进行收发数据
extern DMA_HandleTypeDef hdma_usart1_rx;
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{
if(huart==&huart1)
{
HAL_UART_Transmit_DMA(&huart1,errors,strlen((char*)errors));
}
HAL_UARTEx_ReceiveToIdle_DMA(&huart1,(uint8_t *)RXDATA,2);
__HAL_DMA_DISABLE_IT(&hdma_usart1_rx,DMA_IT_HT);
}
HAL_UARTEx_ReceiveToIdle_DMA(&huart1,(uint8_t*)RXDATA,2);
__HAL_DMA_DISABLE_IT(&hdma_usart1_rx,DMA_IT_HT);
TIM进行PWM输出
随便找一个定时器进行设置
//启动pwm
HAL_TIM_PWM_Start(&htim3,TIM_CHANNEL_1);
//设置占空比 占空比为 50/autoreload
__HAL_TIM_SetCompare(&htim3,TIM_CHANNEL_1,50);
//更改autoreload
__HAL_TIM_SetAutoreload(&htim3,500);
//更改psc值
__HAL_TIM_SET_PRESCALER(&htim3,40);
ADC
板子上r37和r38是两个可调电阻。通过旋钮可以更改输入到pb15.pb12的电压值(当作模拟的信号源)
然后都改为单端输入
double adcget(ADC_HandleTypeDef *pin)
{
int adc;
HAL_ADC_Start(pin);
adc=HAL_ADC_GetValue(pin);
return adc*3.3/4096;
}
adc2 = adcget(&hadc2);
TIM输入捕获
R39和R40可以通过旋钮改变生成pwm的频率,此pwm是外界的(也就是模拟信号源)
设置定时器为输入捕获
设置计数频率和上升沿捕获
//初始化定时器
HAL_TIM_IC_Start_IT(&htim2,TIM_CHANNEL_1);
//在关于定时器回调函数里进行处理
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
int count;
if(htim->Instance==TIM2)
{
//读出来计数值
count=HAL_TIM_ReadCapturedValue(&htim2,TIM_CHANNEL_1);
//重置计数值
__HAL_TIM_SET_COUNTER(&htim2,0);
//计数值*1/捕获频率=周期----然后它的倒数就是频率
f=1000000/count;
//进行下一次捕获
HAL_TIM_IC_Start_IT(&htim2,TIM_CHANNEL_1);//开启输出捕获中断
}
}
常用的函数
//常用的函数
#include "stdio.h"
#include "stdbool.h"
strcmp 比较字符串
strcpy 复制字符串
strtok 切割字符串
//多轮切割
char* tokenptr = strtok(trtext, ":");
if (tokenptr != NULL)
{
type = tokenptr;
tokenptr = strtok(NULL, ":");
name = tokenptr;
tokenptr = strtok(NULL, ":");
time = tokenptr;
sprintf(buff," DATA");
这个在显示lcd的时候用的多