描述:本文整理了所有嵌入式蓝桥杯可能使用到的函数模块和代码
!!!!!!注意:重点掌握每个函数,函数内容(代码)可自行编写,但是需要调用的HAL库函数是唯一的
II2模块-->>EEPROM读写
------->>注意该模块无HAL库函数调用
此模块通过编写II2时序对具有存储功能的外设进行读写操作,如对M24C02芯片(存储芯片)、MCP4017T芯片(数字电位器)进行操作。
其中M24C02又称为AT24C02---->>>>即eeprom,此模块在竞赛中多次出现,重点需掌握对IIC时序的理解。
MCP4017目前为止未在考题中出现。
---------------------根据官方给出的i2c_hal.c-----------------------
我们编写对eeprom的读写函数。
/**
* @param--address:要将数据写入到eeprom中的地址
* @param--info:写如到eeprom中的数据内容
* @retval: None
*/
void x24c02_write(unsigned char address,unsigned char info)
{
I2CStart();/*开启I2C*/
I2CSendByte(0xa0);/*这里首先要对eeprom进行选择,因为IIC总线能够挂载多个外设,所以这里需要选
I2CWaitAck(); 择外设为eeprom*/
/*下面开始真正对eeprom进行操作*/
I2CSendByte(address);/*选择eeprom的地址*/
I2CWaitAck();/*等待eeprom回应*/
I2CSendByte(info);/*发送要写入到所选地址中的数据*/
I2CWaitAck();/**/
I2CStop();/*关闭I2C*/
}/*编写注意:只要记得在代码开始和完成时分别调用I2CStrat();和I2CStop();
以及在每次发送数据位后调用I2CWaitAck();就可以快速写出代码*/
/**
* @param--address:选择读取哪个存储单元内的数据
* @retval--(uint8_t) val:因为是读操作,所以1必要要将读取到的内容返回,故需要调用return函数
* 注意此时函数从void类型---->>变为uint8_t(返回值的类型)
**/
uint8_t x24c02_read(uint8_t address)
{
unsigned char val;
I2CStart();
I2CSendByte(0xa0);/*选择外设为eeprom*/
I2CWaitAck();
I2CSendByte(address);
I2CWaitAck();
I2CSendByte(0xa1);/*表示对eeprom进行读操作*/
I2CWaitAck();
val = I2CReceiveByte();
I2CStop();
return val;
}
version--2
uchar eeprom_read(uchar addr)
{
uchar dat;
I2CStart();
I2CSendByte(0xa0);//写指令/*1010 000x*//*x(R/W)==1表示read,x==0表示write*//*这里写指令
表示联系芯片*/
I2CWaitAck();
I2CSendByte(addr);/*读的地址*/
I2CWaitAck();
I2CStop();
I2CStart();
I2CSendByte(0xa1);/*读指令*/
I2CWaitAck();
dat=I2CReceiveByte();
I2CWaitAck();
I2CStop();
return dat;
}
void eeprom_write (uchar addr,uchar dat)
{
I2CStart();
I2CSendByte(0xa0);/*表示联系芯片且告知芯片要读取那个存储单元*/
I2CWaitAck();
I2CSendByte(addr);/*写的地址*/
I2CWaitAck();
I2CSendByte(dat);
I2CWaitAck();
I2CStop();
}
TIM定时器模块----->>>>属于最重要的模块
!!!---->此模块调用了最多的HAL库函数,需要着重记忆
在这里定时器分为四个部分:
->TIM
->PWMOUT
->FREQIN
->PWMIN
--------------------------------------------------------TIM----------------------------------------------------
/*以基本定时器TIM6为例,演示定时器的基本定时功能,
以及触发中断后的中断处理函数与中断回调函数*/
HAL_TIM_Base_Start_IT(&htim6);/*定时器基本操作-->开始(定时/更新)中断*/
/*相似函数HAL_TIM_Base_Start(&htim6);表示定时器基础--->开启定时器*/
__HAL_TIM_CLEAR_IT(&htim6,TIM_IT_UPDATE);/*清楚定时器中断标志-->清除类型--更新中断*/
/*注意该函数可有可无!!*/
/**************中断回调函数**********/
/**初始定义为 _weak 需要用户自行编写**/
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if(++led_time == 1000)
{
LED_Time=0;
HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_8);
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_11 |
GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET);
}
}
-----------------------------------------------------------PWMOUT-------------------------------------------------------
HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_2);/*定时器--->PWN开启*/
/*注意区分:HAL_TIM_PWM_Start_IT();---定时器---->PWM 中断开启*/
__HAL_TIM_CLEAR_IT(&htim2,TIM_IT_UPDATE);/*依旧是清除更新中断*/
__HAL_TIM_SET_COMPARE(&htim2,TIM_CHANNEL_2,500);/*函数功能:设置捕获比较寄存器(CCRx)的值*/
------------------------------------------------------------FERQIN--------------------------------------------------------
/*单个定时器输入捕获示例*/
HAL_TIM_IC_Start_IT(&htim3,TIM_CHANNEL_1);/*开启定时器输入捕获中断*/
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)/*输入捕获回调函数*/
{
cc_value = __HAL_TIM_GET_CPUNTER(&htim3);/*获取计数器的值*/
__HAL_TIM_Setcounter(&htim3,0);
f39 = (80000000/(80-1))/cc_value;
} /*上升沿捕获,所以检测到低电平到高电平变化时开始采集-采集一个周期时间,从而计算频率;
CNT-->ARR(CNT==ARR)*/
/*两个定时器输入捕获示例*/
HAL_TIM_IC_Start_IT(&htim3,TIM_CHANNEL_1);
HAL_TIM_IC_Start_IT(&htim2,TIM_CHANNEL_1);
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
/*注意对定时器进行判断*/
if(htim->Instance == TIM3)
{
cc1_value = __HAL_TIM_GET_COUNTER(&htim3);
__HAL_TIM_Setcounter(&htim3,0);
f39 = 1000000/cc1_value;
HAL_TIM_IC_Start_IT(&himt3);/*更新*/
}
if(htim->Instance == TIM2)
{
cc2_value = __HAL_TIM_GET_COUNTER(&htim2);
__HAL_TIM_Setcounter(&htim2,0);
f40 = 1000000/cc2_value;
HAL_TIM_IC_Start_IT(&htim2);
}
}
--------------------------------------------------------------PWMIN--------------------------------------------------------
uint32 Duty = 0;
uint32 Freq = 0;
HAL_TIM_IC_Start_IC(&hitm2,TIM_CHANNEL_1);
HAL_TIM_IC_Start_IC(&htim2,TIM_CHANNEL_2);
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
volatile static uint32_t Freq_val = 0,Duty_val = 0;
if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1)
{
Freq_val = HAL_TIM_ReadCapturedValue(&htim2,TIM_CHANNEL_1)//周期---上升沿
Freq = 1000000/Freq_val;
}
else if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_2)
{
Duty_val = HAL_TIM_ReadCapturedValue(&htim2,TIM_CHANNEL_2)//占空---下降沿
Duty = Duty_val * 100 / Freq_val;
}
}
USART串口通信---->>>开发板与上位机进行转串口通信-----!!!!!重点为UART
!!!!重点掌握UART通信即异步串口通信
该模块的使用也非常简单,只需要调用两个HAL库函数,以及编写一个接收中断回调函数即可
uint8_t str[20];
/*(开发板向上位机)发送数据*/
HAL_UART_Transmit_IT(&huart1,(unsigned char *)"Hello,World.\r\n",16);
/*注意这里发送的是定长数据*/
HAL_UART_Transmit_IT(&huart1,(unsigned char *)str,strlen((char *)str));
只需要在While循环中一直调用HAL_UART_Transmit_IT(……);函数即可实现发送数据功能
/*(开发板接收上位机发送到数据)接收数据*/
uint8_t rx[20];
HAL_UART_Receive_IT(&huart1,(uint8_t *)rx,10);/*注意该函数需要进行初始化,即在main函数前调用,
以便更新中断,时该函数重复执行*/
HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
LCD_DisplayStringLine(Line8, (uint8_t *)(rx));
HAL_UART_Receive_IT(&huart1, (uint8_t *)rx, 10);/*更新*/
}
ADC&DAC-----------模拟信号<->数字信号 转换
该模块的模拟输出可以使用开发板集成的R37、R38两个旋钮,得到电压的值。
这里需要用户子自定义函数,不过函数的内容还是调用HAL库有关ADC的函数
/*******ADC代码示例********/
uint16_t getADC_R37(void)
{
uint16_t adc_value;
HAL_ADC_Start(&hadc2);
HAL_ADC_PollForConversion(&hadc2,10);/*这里设置一个超时时间,等待常规组转换完成*/
adc_value = HAL_ADC_GetValue(&hadc2);
HAL_ADC_Stop(&hadc2);
return (adc_value *3.3 /4096);/*ADC值的转换-这里总电压为3.3V,ADC精度为12位2^12 == 4096*/
}
uint16_t getADC_R38(void)
{
uint16_t adc_value;
HAL_ADC_Start(&hadc1);
HAL_ADC_PollForConversion(&hadc1,10);
adc_value = HAL_ADC_GetValue(&hadc1);
HAL_ADC_Stop(&hadc1);
return (adc_value *3.3/4096);
}
/*******DAC代码示例**********/
HAL_DAC_Start(&hdac1,DAC_CHANNEL_1);
DAC1_Set_Vol(2.57);
HAL_Delay(1000);
DAC1_Set_Vol(1.25);
HAL_Delay(1000);
void DAC_Set_Vol(float vol)
{
uint16_t temp;
temp = (4096*vol/3.3f);
HAL_DAC_SetValue(&hdac1, DAC_CHANNEL_1,DAC_ALIGN_12B_R,temp);
}
version--2
double getADC(ADC_HandleTypeDef *pin)
{
uint adc;
HAL_ADC_Start (pin);
adc = HAL_ADC_GetValue(pin);
return adc*3.3/4096;
}