一、key和led
使用结构体,让定时器10ms扫一次按键
struct key{
uint8_t key_next;
uint8_t key_flag;
uint8_t key_up;
uint8_t key_long_flag;
uint8_t key_time;
};
struct key keys[4]={0,0,0};
if(htim->Instance==TIM2)
{
keys[0].flag= HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_0);//b1
keys[1].flag= HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_1);//b2
keys[2].flag= HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_2);//b3
keys[3].flag= HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0);//b4
for(i=0;i<4;i++)
switch(keys[i].next){
case 0 : if(keys[i].flag==0){
keys[i].next=1;
keys[i].timer=0;
}break;
case 1 : if(keys[i].flag==0){
keys[i].next=2;
}else{
keys[i].next=0;
}break;
case 2 : if(keys[i].flag==1){
keys[i].next=0;
if(keys[i].timer<70){
keys[i].short_flag=1;
}
}else{
keys[i].timer++;
if(keys[i].timer>70){
keys[i].long_flag=1;
}
}break;
}
}
led显示
void LED_Disp(unsigned char dsLED)
{
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);//开锁存器
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_All,GPIO_PIN_SET);//所有LED熄灭(l小写)
HAL_GPIO_WritePin(GPIOC,dsLED<<8,GPIO_PIN_RESET);//左移8位:控制C8-15引脚,值为1的点亮
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);//关锁存器
}
//打开对应led
led_1|=0x01;
LED_Disp(led_1);
//流水灯高4位
led_1 &= 0x0f;
led_1 |= (1<<LED_flow_up);
LED_flow_up ++ ;
if(LED_flow_up == 8)
LED_flow_up = 4;
二、uart
串口重定向(包含stdio.h,魔法棒勾选)
int fputc(int ch,FILE *f){
HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 1000);
return ch;
}
串口接收(main.c函数打开接收中断) memset函数包含头文件string.h
使用这个函数HAL_UART_Receive_IT(&huart1,&aRxBuffer,1);
uint8_t aRxBuffer; //接收中断缓冲
uint8_t Uart1_RxBuff[10] = {0}; //接收缓冲
uint8_t Uart1_Rx_Cnt = 0; //接收缓冲计数
//回调函数
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
UNUSED(huart);
Uart1_RxBuff[Uart1_Rx_Cnt++] = aRxBuffer; //接收数据转存
HAL_UART_Receive_IT(&huart1, (uint8_t *)&aRxBuffer, 1); //再开启接收中断
}
//用户实现中断调用或者main函数调用
void uart(void){
if(Uart1_Rx_Cnt==7){
if(('0'<=Uart1_RxBuff[0]&&Uart1_RxBuff[0]<='9')&&('0'<=Uart1_RxBuff[1]&&Uart1_RxBuff[1]<='9')
&&('0'<=Uart1_RxBuff[2]&&Uart1_RxBuff[2]<='9')&&(Uart1_RxBuff[3]=='-')&&
('0'<=Uart1_RxBuff[4]&&Uart1_RxBuff[4]<='9')&&('0'<=Uart1_RxBuff[5]&&Uart1_RxBuff[5]<='9')
&&('0'<=Uart1_RxBuff[6]&&Uart1_RxBuff[6]<='9'))
{
Uart1_RxBuff[0]-=0x30;//将字符数据转换为整型数据,反之则相加
Uart1_RxBuff[1]-=0x30;
Uart1_RxBuff[2]-=0x30;
if((key_data[0]==Uart1_RxBuff[0]) && (key_data[1]==Uart1_RxBuff[1])
&&(key_data[1]==Uart1_RxBuff[1]))
{
key_data[0]=Uart1_RxBuff[4]-0x30;
key_data[1]=Uart1_RxBuff[5]-0x30;
key_data[2]=Uart1_RxBuff[6]-0x30;
Uart1_Rx_Cnt = 0;
memset(Uart1_RxBuff,0x00,sizeof(Uart1_RxBuff));//清除内存
}
}
}
}
//得到一个十位数as
data=(Uart1_RxBuff[6]-0x30)*10+Uart1_RxBuff[7]-0x30;
三、tim
使能定时器
预分频系数设置为 8000-1, fCK_CNT=80MHz/8000=10KHz。 这样就得到计数器的计数频率为 10KHz,即计数器 1 秒钟可以计 10000 个数。
//纯定时器回调函数
__weak void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
UNUSED(htim);
/* 用户内容 */
}
/*
//打开定时器 打开地方用户自定义
HAL_TIM_Base_Start_IT(&htim4);
//关闭定时器
HAL_TIM_Base_Stop_IT(&htim2);
*/
四、pwm
80Mhz/80=1Mhz 的计数频率,自动重装载为 500,那么 PWM 频率为 1Mhz/500=2kHZ
HZ计算公式:80000000/80/1000hz=1000(计数值)
占空比 上图:500-1
输入分频系数 以及 计数值
//开启输出pwm 开启地方自定义
HAL_TIM_PWM_Start(&htim5, TIM_CHANNEL_3);
//用户可自定义修改
__HAL_TIM_SET_AUTORELOAD(&htim5,499);//设置自动重装载值
__HAL_TIM_SET_COMPARE(&htim5,TIM_CHANNEL_3,50);//设置占空比
五、捕获输入
十四届省赛考过,说明国赛考点下放也需要学习除了扩展版的所有考点
分频系数为80-1
通道一为上升沿 通道二为下降沿
uint32_t ccr1_val2a=0;
uint32_t ccr1_val2b=0;
uint16_t frq2=0;//频率
uint32_t duty=0;//占空比
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
if(htim->Instance==TIM3)
{
if(htim->Channel==HAL_TIM_ACTIVE_CHANNEL_1)//中断消息来源 选择直接输入的通道
{
ccr1_val2a=HAL_TIM_ReadCapturedValue(htim,TIM_CHANNEL_1);
ccr1_val2b=HAL_TIM_ReadCapturedValue(htim,TIM_CHANNEL_2);
__HAL_TIM_SetCounter(htim,0);
frq2=(80000000/80)/ccr1_val2a;
duty=(ccr1_val2b*100)/ccr1_val2a;
HAL_TIM_IC_Start(htim,TIM_CHANNEL_1);
HAL_TIM_IC_Start(htim,TIM_CHANNEL_2);
}
}
}
六、lcd
包含官方库文件(复制以下文件到自己工程中)
//main函数调用
LCD_Init();
LCD_Clear(Black);
LCD_SetBackColor(Black);
LCD_SetTextColor(White);
//用户使用
if(set_cnt==2)LCD_SetBackColor(Blue);
else LCD_SetBackColor(Black);//高亮
//基础显示
LCD_DisplayStringLine(Line1, (unsigned char *)" Data ");
sprintf(cnbr_lcd," CNBR:%d ",cnbr);
LCD_DisplayStringLine(Line3, (unsigned char *)cnbr_lcd);
//单字符高亮
if(flag == 1&&set_flag) LCD_SetBackColor(Blue);//状态1-Seeting状态 高亮显示小时
LCD_DisplayChar(Line4 , (320 - (16 * 6)) , hour/10 + 0x30);
LCD_DisplayChar(Line4 , (320 - (16 * 7)) , hour%10 + 0x30);
LCD_SetBackColor(Black);
LCD_DisplayChar(Line4 , (320 - (16 * 8)) , ':');
if(flag == 2&&set_flag) LCD_SetBackColor(Blue); //状态2-Seeting状态 高亮显示分钟
LCD_DisplayChar(Line4 , (320 - (16 * 9)) , min/10 + 0x30);
LCD_DisplayChar(Line4 , (320 - (16 * 10)) , min%10 + 0x30);
LCD_SetBackColor(Black);
LCD_DisplayChar(Line4 , (320 - (16 * 11)) , ':');
if(flag == 3&&set_flag) LCD_SetBackColor(Blue); //状态3-Seeting状态 高亮显示秒
LCD_DisplayChar(Line4 , (320 - (16 * 12)) , s/10 + 0x30);
LCD_DisplayChar(Line4 , (320 - (16 * 13)) , s%10 + 0x30);
LCD_SetBackColor(Black);
七、adc输入 与dac输出
adc输入
官方一般使用PB15引脚
//adc
double rd_adc(ADC_HandleTypeDef* hadc)
{
unsigned int adc_data=0;
HAL_ADC_Start(hadc);
adc_data=HAL_ADC_GetValue(hadc);
return adc_data*3.3/4096;
}
dac输出
HAL_DAC_Start(&hdac1,DAC_CHANNEL_1); // main函数使能DAC1的通道1
DAC1_Set_Vol(1.50); // 调用DAC1设置电压函数
void DAC1_Set_Vol(float vol)
{
uint32_t temp; // 定义电压转换后的数值
temp = (4096 * vol/3.3f); // 12位的DAC最大数值为4096,vol / 3.3 就是设置的电压所占全部电压(3.3V)的比例
HAL_DAC_SetValue(&hdac1, DAC_CHANNEL_1,DAC_ALIGN_12B_R,temp); // 最终的电压设置函数
}
八、iic-----eeprom
main函数调用
I2CInit();//初始化
以下为连读连写代码
void byte_write(uint8_t addr,uint8_t *data){
I2CStart();
I2CSendByte(0xa0);
I2CWaitAck();
I2CSendByte(addr);
I2CWaitAck();
I2CSendByte(data[0]);
I2CWaitAck();
I2CSendByte(data[1]);
I2CWaitAck();
I2CSendByte(data[2]);
I2CWaitAck();
I2CStop();
}
void read(uint8_t addr ,uint8_t *data)
{
I2CStart();
I2CSendByte(0xa0);
I2CWaitAck();
I2CSendByte(addr);
I2CWaitAck();
I2CStart();//重新开始
I2CSendByte(0xa1);
I2CWaitAck();
data[0]=I2CReceiveByte();
I2CSendAck();//发送响应
data[1]=I2CReceiveByte();
I2CSendAck();
data[2]=I2CReceiveByte();
I2CSendNotAck();
I2CStop();
}
iic——eeprom存入浮点数
extern double x_1,y_1;
uint8_t data[4]={0};
//写入
data[2]=(uint8_t)(x_1*10);
data[3]=(uint8_t)(y_1*10);
wite(0,data);
//读取
read(0,data);
x_1=data[2]/10.0;
y_1=data[3]/10.0;
九、定时器
配合定时器使用
if(s==0)
{
if(min!=0||hour!=0)
{
s=59;
if(min!=0)
min-=1;
else if(hour!=0)
{
min=59;
hour-=1;
}
}
}else if(s!=0)
s-=1;
if(flag==1) { hour+=1; if(hour>59) hour=0;}
else if(flag==2) { min+=1; if(min>59) min=0; }
else if(flag==3) { s+=1; if(s>59) s=0; }
十、rtc
RTC_TimeTypeDef stime;
RTC_DateTypeDef sdate;
void get_time (void)
{
HAL_RTC_GetTime(&hrtc, &stime, RTC_FORMAT_BIN);
HAL_RTC_GetDate(&hrtc, &sdate, RTC_FORMAT_BIN);
}
sprintf(time," %d:%d:%d ",stime.Hours,stime.Minutes,stime.Seconds);
LCD_DisplayStringLine(Line7, (uint8_t *)time);
十一、冒泡排序
void lit(void)
{
uint8_t i, j, temp;
hight[0]=threshold1_data;
hight[1]=threshold2_data;
hight[2]=threshold3_data;
for (i = 1; i <= 2; i++)//外部总共要遍历n-1次(n为元素个数)
{
for (j = 0; j <= 2 - i; j++)//每一次将最大值放在最后以后,前面的数两者比较次数-1
{
if (hight[j] > hight[j + 1])
{
temp = hight[j];
hight[j] = hight[j + 1];
hight[j + 1] = temp;
}
}
}
}