我是靠谱客的博主 美丽狗,最近开发中收集的这篇文章主要介绍stm32f4外设学习篇(代码集合)1、串口12、串口2(RS485)3、定时器(多路)4、PWM5、窗口看门狗6、独立看门狗7、GPIO(LED)8、外部中断(EXTI)9、随机数发生器10、ADC11、DAC12、DMA13、IIC14、SPI15、24C0216、W25QXX完整工程,觉得挺不错的,现在分享给大家,希望可以做个参考。
概述
stm32f4外设学习篇(代码集合)
- 1、串口1
- 2、串口2(RS485)
- 3、定时器(多路)
- 4、PWM
- 5、窗口看门狗
- 6、独立看门狗
- 7、GPIO(LED)
- 8、外部中断(EXTI)
- 9、随机数发生器
- 10、ADC
- 11、DAC
- 12、DMA
- 13、IIC
- 14、SPI
- 15、24C02
- 16、W25QXX
- 完整工程
芯片:STM32F407(理论支持F4所有芯片)
开发环境:KEIL5-ARM
目的:单独的文件除了24c02和W25QXX会需要依赖iic和spi其余文件都是可以直接拷贝到工程使用的
日期:2021-8-12
有一些外设并没有经过测试所以在使用过程中自行调试
1、串口1
.c文件
#include "debug_usart.h"
/**
* @brief DEBUG_USART GPIO 配置,工作模式配置。115200 8-N-1
* @param 无
* @retval 无
*/
void Debug_USART_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
RCC_AHB1PeriphClockCmd(DEBUG_USART_RX_GPIO_CLK | DEBUG_USART_TX_GPIO_CLK, ENABLE);
/* 使能 UART 时钟 */
RCC_APB2PeriphClockCmd(DEBUG_USART_CLK, ENABLE);
/* 连接 PXx 到 USARTx_Tx*/
GPIO_PinAFConfig(DEBUG_USART_RX_GPIO_PORT, DEBUG_USART_RX_SOURCE, DEBUG_USART_RX_AF);
/* 连接 PXx 到 USARTx__Rx*/
GPIO_PinAFConfig(DEBUG_USART_TX_GPIO_PORT, DEBUG_USART_TX_SOURCE, DEBUG_USART_TX_AF);
/* 配置Tx引脚为复用功能 */
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Pin = DEBUG_USART_TX_PIN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(DEBUG_USART_TX_GPIO_PORT, &GPIO_InitStructure);
/* 配置Rx引脚为复用功能 */
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Pin = DEBUG_USART_RX_PIN;
GPIO_Init(DEBUG_USART_RX_GPIO_PORT, &GPIO_InitStructure);
/* 配置串DEBUG_USART 模式 */
USART_InitStructure.USART_BaudRate = DEBUG_USART_BAUDRATE;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
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(DEBUG_USART, &USART_InitStructure);
USART_Cmd(DEBUG_USART, ENABLE);
}
u8 USART_RX_BUF[USART_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.
//接收状态
//bit15, 接收完成标志
//bit14, 接收到0x0d
//bit13~0, 接收到的有效字节数目
u16 USART_RX_STA = 0; //接收状态标记
void USART1_IRQHandler(void) //串口1中断服务程序
{
u8 Res;
if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //接收中断(接收到的数据必须是0x0d 0x0a结尾)
{
Res = USART_ReceiveData(USART1); //(USART1->DR); //读取接收到的数据
if ((USART_RX_STA & 0x8000) == 0) //接收未完成
{
if (USART_RX_STA & 0x4000) //接收到了0x0d
{
if (Res != 0x0a)
USART_RX_STA = 0; //接收错误,重新开始
else
USART_RX_STA |= 0x8000; //接收完成了
}
else //还没收到0X0D
{
if (Res == 0x0d)
USART_RX_STA |= 0x4000;
else
{
USART_RX_BUF[USART_RX_STA & 0X3FFF] = Res;
USART_RX_STA++;
if (USART_RX_STA > (USART_REC_LEN - 1))
USART_RX_STA = 0; //接收数据错误,重新开始接收
}
}
}
}
}
//buf:接收缓存首地址
//len:读到的数据长度
void get_uart_buff(uint8_t *buf, uint8_t *len)
{
u8 rxlen = USART_RX_STA;
u8 i = 0;
*len = 0; //默认为0
_uart_delay(0xff); //等待10ms,连续超过10ms没有接收到一个数据,则认为接收结束
if (rxlen == USART_RX_STA && rxlen) //接收到了数据,且接收完成了
{
for (i = 0; i < rxlen; i++)
{
buf[i] = USART_RX_BUF[i];
}
*len = USART_RX_STA; //记录本次数据长度
USART_RX_STA = 0; //清零
}
}
//重定向c库函数printf到串口DEBUG_USART,重定向后可使用printf函数
int fputc(int ch, FILE *f)
{
/* 发送一个字节数据到串口DEBUG_USART */
USART_SendData(DEBUG_USART, (uint8_t)ch);
/* 等待发送完毕 */
while (USART_GetFlagStatus(DEBUG_USART, USART_FLAG_TXE) == RESET)
;
return (ch);
}
//重定向c库函数scanf到串口DEBUG_USART,重写向后可使用scanf、getchar等函数
int fgetc(FILE *f)
{
/* 等待串口输入数据 */
while (USART_GetFlagStatus(DEBUG_USART, USART_FLAG_RXNE) == RESET)
;
return (int)USART_ReceiveData(DEBUG_USART);
}
/*********************************************END OF FILE**********************/
.h文件
#ifndef __DEBUG_USART_H
#define __DEBUG_USART_H
#include "stm32f4xx.h"
#include <stdio.h>
//引脚定义
/*******************************************************/
#define DEBUG_USART USART1
#define DEBUG_USART_CLK RCC_APB2Periph_USART1
#define DEBUG_USART_RX_GPIO_PORT GPIOA
#define DEBUG_USART_RX_GPIO_CLK RCC_AHB1Periph_GPIOA
#define DEBUG_USART_RX_PIN GPIO_Pin_10
#define DEBUG_USART_RX_AF GPIO_AF_USART1
#define DEBUG_USART_RX_SOURCE GPIO_PinSource10
#define DEBUG_USART_TX_GPIO_PORT GPIOA
#define DEBUG_USART_TX_GPIO_CLK RCC_AHB1Periph_GPIOA
#define DEBUG_USART_TX_PIN GPIO_Pin_9
#define DEBUG_USART_TX_AF GPIO_AF_USART1
#define DEBUG_USART_TX_SOURCE GPIO_PinSource9
#define USART_REC_LEN 200 //定义最大接收字节数 200
extern uint8_t USART_RX_BUF[USART_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.末字节为换行符
extern uint16_t USART_RX_STA; //接收状态标记
/************************************************************/
// 不精确的延时
static void _uart_delay(__IO u32 nCount)
{
for (; nCount != 0; nCount--)
;
}
//串口波特率
#define DEBUG_USART_BAUDRATE 115200
void Debug_USART_Config(void);
void get_uart_buff(uint8_t *buf, uint8_t *len);
int fputc(int ch, FILE *f);
#endif /* __USART1_H */
2、串口2(RS485)
.c文件
#include "rs485.h"
// 配置USART接收中断
static void NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
/* Configure the NVIC Preemption Priority Bits */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
/* Enable the USARTy Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = _485_INT_IRQ;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
/*
* 函数名:_485_Config
* 描述 :USART GPIO 配置,工作模式配置
* 输入 :无
* 输出 : 无
* 调用 :外部调用
*/
void _485_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
USART_ClockInitTypeDef USART_ClockInitStruct;
RCC_AHB1PeriphClockCmd(_485_USART_RX_GPIO_CLK | _485_USART_TX_GPIO_CLK | _485_RE_GPIO_CLK, ENABLE);
RCC_APB1PeriphClockCmd(_485_USART_CLK, ENABLE);
USART_DeInit(_485_USART);
USART_StructInit(&USART_InitStructure);
USART_ClockStructInit(&USART_ClockInitStruct);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; //复用
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽输出
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_InitStructure.GPIO_Pin = _485_USART_TX_PIN;
GPIO_Init(_485_USART_TX_GPIO_PORT, &GPIO_InitStructure);
GPIO_PinAFConfig(_485_USART_TX_GPIO_PORT, GPIO_PinSource3, GPIO_AF_USART2);
GPIO_InitStructure.GPIO_Pin = _485_USART_RX_PIN;
GPIO_Init(_485_USART_RX_GPIO_PORT, &GPIO_InitStructure);
GPIO_PinAFConfig(_485_USART_RX_GPIO_PORT, GPIO_PinSource2, GPIO_AF_USART2);
USART_ClockInit(_485_USART, &USART_ClockInitStruct);
USART_InitStructure.USART_BaudRate = _485_USART_BAUDRATE; //波特率设置
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
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(_485_USART, &USART_InitStructure);
USART_ITConfig(_485_USART, USART_IT_RXNE, ENABLE); //接收中断使能
USART_ClearITPendingBit(_485_USART, USART_IT_TC); //清除中断TC位
USART_Cmd(_485_USART, ENABLE); //使能串口
USART_ClearFlag(_485_USART, USART_FLAG_TC);
/***********************************GPIOA 1,RS485方向控制******************************/
GPIO_InitStructure.GPIO_Pin = _485_RE_PIN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(_485_RE_GPIO_PORT, &GPIO_InitStructure);
NVIC_Configuration();
/* 使能串口接收中断 */
USART_ITConfig(_485_USART, USART_IT_RXNE, ENABLE);
GPIO_ResetBits(_485_RE_GPIO_PORT, _485_RE_PIN); //默认进入接收模式
}
/***************** 发送一个字符 **********************/
//使用单字节数据发送前要使能发送引脚,发送后要使能接收引脚。
void _485_SendByte(uint8_t ch)
{
/* 发送一个字节数据到USART1 */
USART_SendData(_485_USART, ch);
/* 等待发送完毕 */
while (USART_GetFlagStatus(_485_USART, USART_FLAG_TXE) == RESET)
;
}
/***************** 发送指定长度的字符串 **********************/
void _485_SendStr_length(uint8_t *str, uint32_t strlen)
{
unsigned int k = 0;
_485_TX_EN(); // 使能发送数据
do
{
_485_SendByte(*(str + k));
k++;
} while (k < strlen);
_485_delay(0xfff);
_485_RX_EN(); // 使能接收数据
}
/***************** 发送字符串 **********************/
void _485_SendString(uint8_t *str)
{
unsigned int k = 0;
_485_TX_EN(); // 使能发送数据
do
{
_485_SendByte(*(str + k));
k++;
} while (*(str + k) != '