
#训练营#STM32天空星拓展板
简介
基于天空星高配版,f407系列真的挺强的,使用eda专业版自主设计原理图和pcb,板子两个电位器的io配置有问题。已经附上源码,都是模块化好的。
简介:基于天空星高配版,f407系列真的挺强的,使用eda专业版自主设计原理图和pcb,板子两个电位器的io配置有问题。已经附上源码,都是模块化好的。开源协议
:GPL 3.0
描述
Keil5配置

2024年9月9日
11:02

lcd驱动(需要外部导入相关库文件)



将这三个文件放入所建工程的组文件中(模块化的调用相当是)


LCD_Init(); //初始化lcd
LCD_Clear(Black);// 清屏并显示初始背景色
LCD_SetBackColor(Black); //背景颜色
LCD_SetTextColor(White); //字体颜色
char miao[10];
int hh = 0;
sprintf(miao," %d",hh); // 转换函数 需要包含stdio.h 头文件
//将需要的内容打印到字符串中
//我理解为将后边hh整形数据存入 miao[]数组中,再用下边函数指针取首地址向后输入 LCD_DisplayStringLine(Line1, (u8 *)miao);
//lcd屏幕字符输出函数,行+内容
CubeMx配置
2024年9月9日
10:56
创建新工程:
1,芯片选型(正确的芯片型号,正确的封装

2,Debug选择

3,时钟配置,先根据需要开启时钟,再对时钟树进行配置

时钟树配置时要根据板子实际外部晶振进行调整

4,GPIO配置



小提示
2024年9月9日
11:01
keil5使用的时候ctrl + alt +空格显示提示词需要有键盘模式


重定义变量类型
2024年9月9日
10:50
typedef signed char int8_t; //给有符号char,取别名为int8_t
typedef signed short int int16_t; //给有符号短整型short int,取别名int16_t
typedef signed int int32_t; //给有符号整型short int,取别名int32_t
typedef signed __INT64 int64_t; typedef unsigned char uint8_t; //给无符号char,取别名为uint8_t
typedef unsigned short int uint16_t;//给无符号短整型short int,取别名为uint16_t
typedef unsigned int uint32_t; //给无符号整型short int,取别名为uint32_t
typedef unsigned __INT64 uint64_t;
/* 7.18.1.2 */ //和上面一样,取其他别名
/* smallest type of at least n bits */
/* minimum-width signed integer types */
typedef signed char int_least8_t;
typedef signed short int int_least16_t;
typedef signed int int_least32_t;
typedef signed __INT64 int_least64_t;
/* minimum-width unsigned integer types */
typedef unsigned char uint_least8_t;
typedef unsigned short int uint_least16_t;
typedef unsigned int uint_least32_t;
typedef unsigned __INT64 uint_least64_t;
/* fastest minimum-width signed integer types */
typedef signed int int_fast8_t;
typedef signed int int_fast16_t;
typedef signed int int_fast32_t;
typedef signed __INT64 int_fast64_t;
/* fastest minimum-width unsigned integer types */
typedef unsigned int uint_fast8_t;
typedef unsigned int uint_fast16_t;
typedef unsigned int uint_fast32_t;
typedef unsigned __INT64 uint_fast64_t;
定时器中断
2024年9月9日
11:03

HAL_TIM_Base_Start_IT(TIM_HandleTypeDef *htim); //开启时钟中断,必要函数,但是注意放在定时器初始化函数之后
配置中断可通过两种方式
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if (htim->Instance == TIM1) // 确保是 TIM1 定时器触发了回调
{
// 在这里添加你的代码,例如更新变量、触发中断等
}
}
void TIM3_IRQHandler(void)
{
HAL_TIM_IRQHandler(&htim3)
//中断处理函数
}


定时器的定时计算:
开启定时器中断后,定时器每完成一次计时会进入一次中断服务函数。
中断:
抢占优先级,响应优先级;
多个中断请求时,根据抢占、响应的顺序先后进行。(低优先的中断可被高优先中断打断)
抢占、响应优先级都相同时,系统根据自然排序处理。
(所以中断一定有前后顺序)


对定时器的理解:
定时器是独立的计数器,不受中断影响,即使进入中断,定时器也会不断计数。
所以用定时器来取代delay 延时,每当计数完成一次 才会进入一次中断处理函数,此时程序进入中断服务函数,但这个时间极其短暂(我认为可以忽略),相比delay程序停下来能获得更好的延时方案。
外部中断(以按键中断为例)
2024年9月9日
11:09

void EXTI1_IRQHandler(void) { HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_1);
// 外部中断处理函数 }
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
//在hal_gpio.c中,是外部中断的回调函数,需放在主函数下
}

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if(GPIO_Pin == GPIO_PIN_12)
{
}
}//多按键中断回调处理函数
SPI通信
2024年9月9日
10:54


SPI 是英语Serial Peripheral interface的缩写,顾名思义就是串行外围设备接口。是Motorola(摩托罗拉)首先在其MC68HCXX系列处理器上定义的。
SPI,是一种高速的,全双工,同步的通信总线,并且在芯片的管脚上只占用四根线,节约了芯片的管脚,同时为PCB的布局上节省空间,提供方便,主要应用在 EEPROM,FLASH,实时时钟,AD转换器,还有数字信号处理器和数字信号解码器之间。
SPI主从模式
SPI分为主、从两种模式,一个SPI通讯系统需要包含一个(且只能是一个)主设备,一个或多个从设备。提供时钟的为主设备(Master),接收时钟的设备为从设备(Slave),SPI接口的读写操作,都是由主设备发起。当存在多个从设备时,通过各自的片选信号进行管理。
SPI是全双工且SPI没有定义速度限制,一般的实现通常能达到甚至超过10 Mbps
SPI信号线
SPI接口一般使用四条信号线通信:
SDI(数据输入),SDO(数据输出),SCK(时钟),CS(片选)
MISO: 主设备输入/从设备输出引脚。该引脚在从模式下发送数据,在主模式下接收数据。 MOSI: 主设备输出/从设备输入引脚。该引脚在主模式下发送数据,在从模式下接收数据。 SCLK:串行时钟信号,由主设备产生。 CS/SS:从设备片选信号,由主设备控制。它的功能是用来作为“片选引脚”,也就是选择指定的从设备,让主设备可以单独地与特定从设备通讯,避免数据线上的冲突。
SPI通信
2024年9月9日
10:54


SPI 是英语Serial Peripheral interface的缩写,顾名思义就是串行外围设备接口。是Motorola(摩托罗拉)首先在其MC68HCXX系列处理器上定义的。
SPI,是一种高速的,全双工,同步的通信总线,并且在芯片的管脚上只占用四根线,节约了芯片的管脚,同时为PCB的布局上节省空间,提供方便,主要应用在 EEPROM,FLASH,实时时钟,AD转换器,还有数字信号处理器和数字信号解码器之间。
SPI主从模式
SPI分为主、从两种模式,一个SPI通讯系统需要包含一个(且只能是一个)主设备,一个或多个从设备。提供时钟的为主设备(Master),接收时钟的设备为从设备(Slave),SPI接口的读写操作,都是由主设备发起。当存在多个从设备时,通过各自的片选信号进行管理。
SPI是全双工且SPI没有定义速度限制,一般的实现通常能达到甚至超过10 Mbps
SPI信号线
SPI接口一般使用四条信号线通信:
SDI(数据输入),SDO(数据输出),SCK(时钟),CS(片选)
MISO: 主设备输入/从设备输出引脚。该引脚在从模式下发送数据,在主模式下接收数据。 MOSI: 主设备输出/从设备输入引脚。该引脚在主模式下发送数据,在从模式下接收数据。 SCLK:串行时钟信号,由主设备产生。 CS/SS:从设备片选信号,由主设备控制。它的功能是用来作为“片选引脚”,也就是选择指定的从设备,让主设备可以单独地与特定从设备通讯,避免数据线上的冲突。
串口通信
2024年9月9日
11:15

I2C是半双工,SPI的全双工,uart是全双工
USART:通用同步和异步收发器
UART:通用异步收发器
当进行异步通信时,这两者是没有区别的。区别在于USART比UART多了同步通信功能。 这个同步通信功能可以把USART当做SPI来用,比如用USART来驱动SPI设备。
阻塞式发送:单片机等发送完毕,期间不做其他事
非阻塞式发送:使能发送中断,发送完毕回调函数
HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart, uint8_t*pData, uint16_t Size,uint32_t Timeout);//阻塞式发送
HAL_StatusTypeDef HAL_UART_Transmit_IT(UART_HandleTypeDef *huart,uint8_t*pData,uint16_t Size);//非阻塞式发送
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart);//回调函数
void HAL_UART_TxHalfCpltCallback(UART_HandleTypeDef *huart);//一半回调函数
HAL_StatusTypeDef HAL_UART_Receive(UART_HandleTypeDef *huart, uint8_t*pDa ta, uint16_t Sizeuint32_t Tim neout);//阻塞式接收 HAL_StatusTypeDef HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size);//非阻塞式接收 void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart);void HAL_UART_RxHalfCpltCallback(UART_HandleTypeDef *huart);

进行串口发送、接收时要清楚串口对应的引脚号。
ch340 RX接单片机TX
TX接单片机RX 一定要共地!!!!!!!
串口调试工具

标准库
void Uart1_init(u32 bound){
//GPIO端口设置
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE); //使能USART1,GPIOA时钟
//USART1_TX GPIOA.9
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.9
//USART1_RX GPIOA.10初始化
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//PA10
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.10
//USART 初始化设置
USART_InitStructure.USART_BaudRate = bound;//串口波特率
USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位
USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制 USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收发模式
USART_Init(USART1, &USART_InitStructure); //初始化串口1
//USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启串口接受中断
USART_Cmd(USART1, ENABLE); //使能串口1
}
编码器驱动
2024年9月9日
11:21
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) //PB12,PB13编码器计数函数
{
if(GPIO_Pin == GPIO_PIN_12)
{
if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_13) == HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_12))
{
key_count--;
} else
{
key_count++;
}
}
}
搭配下边代码同时使用
if(key_count!=0)
{
key_num += key_count;
key_count = 0;
}
注意通过中断处理来确定旋转方向
void EXTI0_IRQHandler(void)//正转:A的上升沿对应B的低电平;反转:B的上升沿对应A的低电平。
{
if (EXTI_GetITStatus(EXTI_Line0) == SET)//判断编码器A是否为高电平,中断是否触发
{
if(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1) ==0)//判断编码器B是否为低电平
{
Encoder_Count++;
}
EXTI_ClearITPendingBit(EXTI_Line0);//如果是,则清空标志位
}
}
void EXTI1_IRQHandler(void)
{
if (EXTI_GetITStatus(EXTI_Line1) == SET)//判断编码器B是否为高电平,中断是否触发
{
if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_0) ==0)//判断编码器A是否为低电平
{
Encoder_Count--;
}
EXTI_ClearITPendingBit(EXTI_Line1);//如果是,则清空标志位
}
}
分别定义两个中断函数EXTI0_IRQHandler和EXTI1_IRQHandler。基本逻辑跟第一小节讲的一样,先判断第一个中断是不是被触发了,即A管脚是否是上升沿。A管脚接的是GPIOB_0,对应的中断0.然后判断B管脚是不是低电平。
EXTI_InitTypeDef EXTI_InitStructure; EXTI_InitStructure.EXTI_Line=EXTI_Line0 | EXTI_Line1;//配置中断线 EXTI_InitStructure.EXTI_LineCmd=ENABLE;//开启或关闭中断 EXTI_InitStructure.EXTI_Mode=EXTI_Mode_Interrupt;//定义中断模式 EXTI_InitStructure.EXTI_Trigger=EXTI_Trigger_Rising;//触发中断方式,选择上升沿触发 EXTI_Init(&EXTI_InitStructure);
两个中断前后优先级区分清楚,先判断一个再判断另一个
oled驱动注意点
2024年9月9日
11:26
首先拉入相关的字库.h文件
oled的.c .h文件 在编译器中包含路径
主函数中包含头文件,
配置硬件iic,只需要把两个通信接口使能即可。
注意时钟频率,主频太高可能影响显示效果。
(硬件IIC是通过IIC控制器硬件模块来实现IIC通信的,而软件IIC是通过软件控制GPIO口来模拟IIC通信)
OLED_Init();//oled初始化文件
char text[20];
sprintf(text,字符(%d),变量);
OLED_ShowString(2,1,text);
清屏问题,设置屏幕背景色等
PWM配置
2024年9月9日
11:27
只需在CubeMx中配置响应的定时器pwm输出通道即可


HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_1);
TIM2->CCR1 = (常数/定时器计数值或定时器溢出值)//控制 tim2 1通道输出pwm占空比
PWM有效驱动两条代码
PWM频率:Freq = CK_PSC/(PSC+1)/(ARR+1)
PWM占空比:Duty = CCR/(ARR+1)
PWM分辨率:Reso = 1/(ARR+1)
TIM定时器PWM1模式与PWM2模式的比较
STM32 定时器的 PWM 存在两种模式,即 PWM1 模式与 PWM2 模式,两种模式相似却又恰恰相反。
PWM1 模式:向上计数,当 TIMx_CNT < TIMx_CCRn 时,定时器 TIMx 的通道 n 为有效电平,否则为无效电平;向下计数,当 TIMx_CNT > TIMx_CCRn 时,定时器 TIMx 的通道 n 为无效电平,否则为有效电平 有效电平,否则为无效电平。
PWM2 模式:向上计数,当 TIMx_CNT < TIMx_CCRn 时,定时器 TIMx 的通道 n 为无效电平,否则为有效电平;向下计数,当 TIMx_CNT > TIMx_CCRn 时,定时器 TIMx 的通道 n 为有效电平,否则为无效电平 无效电平,否则为有效电平。
下面是 PWM1 模式与 PWM2 模式的比较表格图,能够比较直观的反映出两者的区别。
两种PWM模式的比较 注:
全文中的 TIMx 表示 STM32 的定时器,x 表示某个定时器,取值需要根据芯片来定;
全文中的 TIMx_CNT,表示定时器 TIMx 的计数器寄存器值;
全文中的 TIMx_CCRn,表示捕获比较寄存器的值,其中 n 表示某个通道,取值为1、2、3、4;

ADC采样
2024年9月9日
11:29

只需在CubeMx中开始相关引脚adc采样通道


设计图
未生成预览图,请在编辑器重新保存一次BOM
暂无BOM
克隆工程工程成员
知识产权声明&复刻说明
本项目为开源硬件项目,其相关的知识产权归创作者所有。创作者在本平台上传该硬件项目仅供平台用户用于学习交流及研究,不包括任何商业性使用,请勿用于商业售卖或其他盈利性的用途;如您认为本项目涉嫌侵犯了您的相关权益,请点击上方“侵权投诉”按钮,我们将按照嘉立创《侵权投诉与申诉规则》进行处理。
请在进行项目复刻时自行验证电路的可行性,并自行辨别该项目是否对您适用。您对复刻项目的任何后果负责,无论何种情况,本平台将不对您在复刻项目时,遇到的任何因开源项目电路设计问题所导致的直接、间接等损害负责。


评论