https://blog.csdn.net/Zach_z/article/details/80548423
基础部分之基础部分学习
LED
8种工作模式——输入模式
- 浮空输入:管脚什么都不接,浮空着
- 上拉输入:把电位拉高,拉到Vcc
- 下拉输入:把电平拉低
- 模拟输入:通过模数转换,转换成数字信号,应用ADC模拟输入,或低功耗下省电
8种工作模式——输出模式 - 开漏输出: IO输出0接GND,输出1悬空,其吸收电流的能力相对强
- 推挽输出:IO输出0-接GND,1-接VCC,可以输出高电平低电平,连接数字器件
- 复用功能推挽输出
- 复用功能开漏输出:GPIO口被用作第二功能时的配置
LED原理
- 通过一个锁存器控制,使能引脚为PD2
- PC8-PC15对应LED1-LED8
- PC8-PC15同时服用与LCD显示屏数据的高8位
LED函数
引脚写入函数
HAL_GPIO_WritePin() 点亮某个灯
反转引脚状态
HAL_GPIO_TogglePin (GPIOC,GPIO_PIN_8)
寄存器
GPIOx_BSRR是一个32位置位复位寄存器 GPIO_ODR是一个数据输出寄存器
HAL库的使用
stm32g4xxx_hal_gpio.h这类文件里可找到可操作的库函数,stm32cubeMX可直接生成
按键和蜂鸣器
有源蜂鸣器,将直流转换为具有一定周期的脉冲 PB3低电平,蜂鸣器响
按键
stm32g4xx_hal_gpio.h中有对GPIO进行操作的一些函数
- HAL_GPIO_ReadPin 读取GPIO口状态
按键消抖
延时5到10毫秒
if(key==GPIO_PIN_RESET)
{
HAL_DELAY(10);
if(key==GPIO_PIN_RESET)
{
执行操作
}
}
长按检测
stm32g4xx_it_c定义了各种中断函数
LCD9325
262,144色单芯片SoC驱动,分辨率:240RGB*320点 16位数据通信,PC0-PC15
- 该LCD有10行(Line0–Line9),20列。每一个方格的像素是24*16
生成过程
比赛时会提供LCD的驱动代码和例程,因此LCD的引脚初始化不用在STM32cube MX里完成,可以通过导入驱动代码实现
- 在stm32cubeMX里配好基本的时钟,生成一个project
- 在官方提供的驱动代码:lcd_hal_h,lcd_hal.c,fonts.h 添加到该工程中
- 在keil里 add files 加入lcd-hal.c文件,并在主文件中添加 lcd_hal.h的头文件
LCD的应用
考试要求 黑底白字
- LCD_Init():LCD的初始化
我们可以在lcd_hal.c文件中找到一些可使用的函数
LCD_DisplayStringLine(Line4 ,(unsigned char *)" Hello,world. ");
LCD_DisplayChar(120,120,0X51);
sprintf函数
我们怎么把从串口处读到的字符显示在显示屏上呢?----先初始化LCD,再借助sprintf和LCD_DisplayStringLine()函数 调用该函数需要添加 stdio.h头文件
sprintf((char*)str," Value:%d ", Num);
sprintf((char*)str," Value:%i ", Num);
sprintf((char*)str," Value:%x ", Num);
sprintf((char*)str," Value:%u%% ", Num);
sprintf((char*)str," Value:%f ", dot);
sprintf((char*)str," Value:%0.2f ", dot);
sprintf((char*)str," Value:%E ", dou);
sprintf((char*)str," Value:%0.2f ABC ", dot);
sprintf((char*)str," Value:%d==%0.2f A ", Num,dot);
sprintf((char*)str," Value:%d ", Num);
LCD_DisplayStringLine(Line8,str);
LCD 和LED联合使用
因为LCD和LED的引脚重合,所以当使用LCD时,LED全亮
- cube初始化时,需要初始化引脚PD2 (LED使能引脚)
- 若要单独使用LCD,不使用LED,则关闭所有LED,关闭PD2
void Close_LED(void)
{
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_8 | 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);
}
- LCD初始化
- 如需操作LED:写LED引脚----->PD2使能------>PD2失能
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_RESET);
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET);
EEPROM、DCP、IIC
EEPROM:电可擦除存储器
I2C的使用
- 在STM32cubeMX中将PB6和PB7打开,生成工程,将官方提供的I2C_hal.c和.h文件放到文件夹内。并add文件I2C_hal.c
I2C写数据
- 启动总线
- 寻找从机(写指令)
- 等待回应
- 选择地址
- 等待回应
- 写数据
- 等待回应
- 结束总线
I2C读数据
- 启动总线
- 寻找从机(写指令)
- 等待回应
- 选择地址
- 等待回应
- 结束总线
- 启动总线
- 寻找从机(读指令)
- 等待回应
- 读数据
- 结束总线
I2C函数
- I2CStart:I2C总线启动函数,需用户调用
- I2CSendByte:写数据函数
- I2CWaitAck:总线等待响应函数,返回值:写入是否成功
- I2CReceiveByte:读取(接收)数据函数,返回读取的数据
- I2CStop:总线停止函数
EEPROM读写函数
EEPROM-AT24C02存储数据,断电再上电可以读取出来 需要用户根据总线读写顺序自己编写
写
void iic_write(unsigned char address,unsigned char info)
{
I2CStart();
I2CSendByte(0xa0);
I2CWaitAck();
I2CSendByte(address);
I2CWaitAck();
I2CSendByte(info);
I2CWaitAck();
I2CStop();
}
读
void iic_read(uint8_t address)
{
I2CStart();
I2CSendByte(0xa0);
I2CWaitAck();
I2CSendByte(address);
I2CWaitAck();
I2CStop();
I2CStart();
I2CSendByte(0xa1);
I2CWaitAck();
val= I2CReceiveByte();
I2CStop();
return(val);
}
mcp4017写函数
数字电位器 写入一个数值(info=0x…),可测量PB14引脚的电压
void mcp4017_write(unsigned char info)
{
I2CStart();
I2CSendByte(0x5e);
I2CWaitAck();
I2CSendByte(info);
I2CWaitAck();
I2CStop();
}
中断
处理器数据传输方式:无条件传输,查询方式,中断方式,直接存储器访问
NVIC: 嵌套向量中断控制器 外部中断控制器:EXTI
外部中断的初始化(NVIC)
- stm32cubeMX配置系统时钟,设置引脚PB0, PB1, PB2
- 设置中断出发条件,在GPIO中选择是上升沿触发还是下降沿触发
- NVIC中启动外部中断
- 设置中断优先级
- 使能外部中断
- 生成keil工程文件
HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin); 清除中断标志位,并直接执行中断回调函数,执行任务处理程序
void HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin)
{
if (__HAL_GPIO_EXTI_GET_IT(GPIO_Pin) != 0x00u)
{
__HAL_GPIO_EXTI_CLEAR_IT(GPIO_Pin);
HAL_GPIO_EXTI_Callback(GPIO_Pin);
}
}
HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin); 用户可重新编写回调函数,这就是中断后 执行的任务
定时器,计数器
初始化
-
stm32cubeMX中开启所需要的定时器。(定时器6或7) -
启动定时器 HAL_TIM_Base_Start_IT (&htim6) 和 HAL_TIM_CLEAR_IT(&htim6,TIM_IT_UPDATE)。需用户自行调用 -
HAL_TIM_PeriodElapsedCallback()用户可自行编写实际的任务处理程序,适用于所有定时器的更新中断
PWMOUT初始化
- stm32cubeMX中:配置好系统时钟
- 配置PWM输出引脚 (扩展引脚 PA1-PA7)
- 启动相关定时器时钟(一般选择内部时钟)
- NVIC打开定时器中断
- 设置分频参数,占空比等
- 生成代码
KEIL
HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_2);
__HAL_TIM_CLEAR_IT(&htim2,TIM_CHANNEL_2);
- 写回调函数 HAL_TIM_IC_CaptureCallback(htim);
内部定时计数器
读取并在LCD屏上显示R39和R40电位器控制的信号源的频率
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(&htim3, TIM_CHANNEL_1);
}
else 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, TIM_CHANNEL_1);
}
while (1)
{
sprintf((char*)str, " FRQ(R39):%dHz ",f39);
LCD_DisplayStringLine(Line8, (uint8_t *)str);
sprintf((char*)str, " FRQ(R40):%dHz ",f40);
LCD_DisplayStringLine(Line9, (uint8_t *)str);
HAL_Delay(200);
}
串口通信
usart1—uart
初始化流程
stm32cubeMX:
- 设置系统时钟
- 设置串口引脚 (PA9, PA10) 注意
- 设置串口参数
- 使能串口中断
Keil:
串口通信的应用
发
收
HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
回调函数(弱定义,用户可自行编写,实际中断所执行的任务处理程序)
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
LCD_DisplayStringLine(Line8,(uint8_t*)(RX));
HAL_UART_Receive_IT(&huart1,(uint8_t*)RX,10);
}
ADC和DAC
ADC初始化
STM32cubeMX:
- 设置系统时钟
- 设置ADC引脚
- 使能ADC对应通道模式
- 设置ADC参数
(一般不需要开启ADC中断)
Keil: ADC无需我们设置中断且初始化函数已由STM32Cube生成,无需其他操作
ADC应用
用户编写
- HAL_ADC_PollForConversion(ADC_HandleTypeDef *hadc, uint32_t Timeout) 等待ADC转换的时间
- HAL_ADC_GetValue(ADC_HandleTypeDef *hadc) 读取ADC的转换结果
- 获取ADC数据并显示
uint16_t getADC_R38(void)
{
uint16_t adc=0;
HAL_ADC_Start(&hadc1);
HAL_ADC_PollForConversion(&hadc1, 10);
adc=HAL_ADC_GetValue(&hadc1);
HAL_ADC_Stop(&hadc1);
return adc;
}
sprintf((char *)str, " R38: %.2fV",getADC_R38()*3.3/4096);
LCD_DisplayStringLine(Line7,(uint8_t *)str);
HAL_Delay(100);
DAC初始化
扩展引脚PA4, PA5支持DAC输出 STM32CubeMX操作:
- 配置系统时钟
- 选中DAC引脚
- 配置DAC引脚
Keil: - DAC启动函数 HAL_DAC_Start(&hdac1, DAC_CHANNEL_1)
*
应用
- HAL_DAC_SetValue()函数------->使对应DAC通道输出设定电压值
- 设定电压值
void DAC1_SET_Vol(float vol)
{
uint16_ttemp;
temp=(4096*vol/3.3f);
HAL_DAC_SetValue(&hdac1,DAC_CHANNEL_1,DAC_ALIGN_12B_R,temp);
}
DAC1_SET_Vol(1.2) 输出1.2V电压
DMA—直接存储器访问
外设和存储器之间高速数据传输
DMA初始化
STM32CubeMX:
- 设置系统时钟
- 串口初始化
- 打开串口DMA
- 设置串口DMA参数
Keil:
- 编写DMA串口收发用户函数
发送一定量的,不定长的数据
RTC— 实时时钟
RTC初始化
STM32CubeMX:
- 设置好系统时钟
- RTC初始化(使用内部时钟)
- 配置RTC初始参数
Keil:
- RTC初始化函数
- 调用RTC用户程序(读取RTC数据)
HAL_RTC_GetTime(&hrtc, , ) /// HAL_RTC_GetDate(&hrtc, ) - 编写RTC用户程序(重新设置RTC数据)
static void RTC_SetTime(uint8_t HH,uint8_t MM,uint8_t SS)
{
RTC_TimeTypeDef sTime = {0};
sTime.Hours = HH;
sTime.Minutes = MM;
sTime.Seconds = SS;
if (HAL_RTC_SetTime(&hrtc, &sTime, RTC_FORMAT_BIN) != HAL_OK)
{
Error_Handler();
}
}
应用
在LCD屏上显示时间
static void RTC_CalendarShow(uint8_t *showtime, uint8_t *showdate)
{
RTC_DateTypeDef sdatestructureget;
RTC_TimeTypeDef stimestructureget;
HAL_RTC_GetTime(&hrtc, &stimestructureget, RTC_FORMAT_BIN);
HAL_RTC_GetDate(&hrtc, &sdatestructureget, RTC_FORMAT_BIN);
sprintf((char *)showtime, "%2d:%2d:%2d", stimestructureget.Hours, stimestructureget.Minutes, stimestructureget.Seconds);
LCD_DisplayStringLine(Line8, (uint8_t *)ShowTime);
sprintf((char *)showdate, "%2d-%2d-%2d", 2000 + sdatestructureget.Year,sdatestructureget.Month, sdatestructureget.Date);
LCD_DisplayStringLine(Line9, (uint8_t *)ShowDate);
}
基础实验之资源扩展板
数码管
引脚连接图 3个数码管各接了一个74HC595的芯片,相当于一个3位的移位寄存器
初始化配置
STM32CubeMX:
- 配置数码管相关引脚(PA1, PA2, PA3)为输出模式
- 生成初始化工程文件
Keil: - 编写数码管驱动程序
硬件连接引脚 共阴极数码管的值
ADC按键
电路原理图
cube配置
Keil编写
- button.c 和button.h文件,考场不提供任何驱动程序,需要会写
DS18B20 温度传感器
初始化
STM32CubeMX: (此处也可不进行操作)
- 设置好系统时钟
- 配置ds18b20相关引脚接口(PA6)
- 生成初始化工程文件
- 添加LCD文件
Keil: - 复制IIC驱动代码 ds18b20_hal.c ds18b20_hal.h至对应的用户文件夹
- 在keil工程中添加相关文件
- 编写一个函数
光敏电阻,ADC
电路图,TRAO引脚
|