1、单片机启动
启动过程,先运行启动文件,启动文件里面有一段汇编代码,先执行汇编代码,接着配置时钟,随即进入主函数。
查看单片机主频
2、自己配置时钟树
stm32的RCC系统时钟配置 以及RCC_PLLConfig(uint32_t RCC_PLLSource, uint32_t PLLM, uint32_t PLLN, uint32_t PLLP, uint32_t PLLQ)的配置 - chaina_家长 - 博客园 (cnblogs.com)
void RCC_Init(void)
{RCC_ClocksTypeDef RCC_Clocks;ErrorStatus HSEStartUpStaus;RCC_DeInit(); // 把RCC外设初始化成复位状态,这句是必须的RCC_ClockSecuritySystemCmd(ENABLE); //使能系统安全RCC_HSEConfig(RCC_HSE_ON); //打开HSE,外部高速时钟HSEStartUpStaus = RCC_WaitForHSEStartUp(); //等待HSE开启if (SUCCESS == HSEStartUpStaus) //成功开始分频{
//----------------------------------------------------------------------//// 使能FLASH 预存取缓冲区FLASH_PrefetchBufferCmd(ENABLE);// SYSCLK周期与闪存访问时间的比例设置,这里统一设置成2// 设置成2的时候,SYSCLK低于48M也可以工作,如果设置成0或者1的时候,// 如果配置的SYSCLK超出了范围的话,则会进入硬件错误,程序就死了// 0:0 < SYSCLK <= 24M// 1:24< SYSCLK <= 48M// 2:48< SYSCLK <= 72MFLASH_SetLatency(FLASH_Latency_2);
//----------------------------------------------------------------------//// AHB预分频因子设置为1分频,HCLK = SYSCLK RCC_HCLKConfig(RCC_SYSCLK_Div1); // APB1预分频因子设置为2分频,PCLK1 = HCLK/2RCC_PCLK1Config(RCC_SYSCLK_Div2); // APB2预分频因子设置为1分频,PCLK2 = HCLKRCC_PCLK2Config(RCC_SYSCLK_Div1); //-----------------设置各种频率主要就是在这里设置-------------------//// 设置PLL时钟来源为HSE,HSE=8MHz
// PLLM:PLL_VCO input clock =(HSE or HSI /PLLM)
// PLLN:PLL_VCO output clock =(PLL_VCP input clock)*PLLN
// PLLP:System Clock =PLL_VCO output clock/PLLP
// PLLQ:配置SD卡读写,USB等功能,暂时不用RCC_PLLConfig(RCC_PLLSource_PREDIV1, RCC_PLLMul_9);
//------------------------------------------------------------------//// 开启PLL RCC_PLLCmd(ENABLE);// 等待 PLL稳定while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET){}// 当PLL稳定之后,把PLL时钟切换为系统时钟SYSCLKRCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);// 读取时钟切换状态位,确保PLLCLK被选为系统时钟while (RCC_GetSYSCLKSource() != 0x08){}}else{ // 如果HSE开启失败,那么程序就会来到这里,用户可在这里添加出错的代码处理// 当HSE开启失败或者故障的时候,单片机会自动把HSI设置为系统时钟,// HSI是内部的高速时钟,8MHZwhile (1){}}}
3、GPIO口使用
3.1、输出模式
// 1、配置GPIO外设时钟RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA | RCC_AHBPeriph_GPIOB | RCC_AHBPeriph_GPIOC | RCC_AHBPeriph_GPIOD | RCC_AHBPeriph_GPIOF | RCC_AHBPeriph_DMA1, ENABLE);GPIO_InitTypeDef GPIO_InitStructure; //配置结构体GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7; //配置的引脚 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; //配置模式,OUTPUT/INPUTGPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //速度50MHzGPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //输出模式GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //是否需要上拉GPIO_Init(GPIOA, &GPIO_InitStructure); //配置A组引脚 GPIO_SetBits(GPIOA,GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7);//引脚设置高电平
//GPIO_ResetBits(GPIOA,GPIO_Pin_0); //A组GPIO引脚0设置低电平
void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin) //置低电平
void GPIO_setBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin) //置高电平
3.2、输入模式
// 1、配置GPIO外设时钟RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA | RCC_AHBPeriph_GPIOB | RCC_AHBPeriph_GPIOC | RCC_AHBPeriph_GPIOD | RCC_AHBPeriph_GPIOF | RCC_AHBPeriph_DMA1, ENABLE);GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8|GPIO_Pin_11|GPIO_Pin_15;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; //根据电路图和芯片配置是否下拉GPIO_Init(GPIOA, &GPIO_InitStructure);
if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0) == 0) //读取电平
3.3、转换功能
通讯类的IIC、ADC等功能
4、NVIC配置 (嵌套中断控制器)
中断-NVIC与EXTI外设详解(超全面)-CSDN博客
void Hardware_NVIC_Init(void) //设置中断优先级
{NVIC_InitTypeDef NVIC_InitStructure;//配置GPIA_Pin_0口中断优先级NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn ; //中断源 PA0中断NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; //抢占优先级NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //优先级NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //是否启用中断NVIC_Init(&NVIC_InitStructure);//配置GPIA_Pin_1口中断优先级NVIC_InitStructure.NVIC_IRQChannel = EXTI1_IRQn ; //中断源 PA0中断NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //抢占优先级NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //优先级NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //是否启用中断NVIC_Init(&NVIC_InitStructure);
}
5、EXTI 外部中断
void EXTI0_Config(void)
{GPIO_InitTypeDef GPIO_InitStructure; //配置结构体EXTI_InitTypeDef EXTI_InitStructure;NVIC_InitTypeDef NVIC_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA ,ENABLE); //打开GPIOA时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); //开启AFIO的时钟//配置EXTI中断相应的引脚GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空输入GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //速度50MHzGPIO_Init(GPIOA, &GPIO_InitStructure);//配置AFIO//连接PA0作为EXTI使用,相同的GPIO_Pin_x不能同时触发中断GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource0 );//配置EXTI中断 //PA0 是EXTI_0EXTI_InitStructure.EXTI_Line = EXTI_Line0; //中断线 PA0,PB0,PC0引脚共用EXTI_Line0中断线EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; //中断模式EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; //下降沿触发EXTI_InitStructure.EXTI_LineCmd = ENABLE; //启用中断线EXTI_Init(&EXTI_InitStructure);EXTI_ClearFlag(EXTI_Line0 ); //清理中断标志位//配置GPIOA_Pin_0口中断优先级NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn ; //中断源,来自中断线EXTI_Line0NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; //抢占优先级NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; //优先级NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //是否启用中断NVIC_Init(&NVIC_InitStructure);
}void EXTI0_IRQHandler(void) //触发EXTI0_IRQ中断源的服务函数
{static int status = 1;if ( SET == EXTI_GetITStatus(EXTI_Line0) ) //检测中断来自哪条中断线,//因为有的中断线共用一个中断处理函数{if (status == 1){GPIO_ResetBits(GPIOB ,GPIO_Pin_9);GPIO_ResetBits(GPIOB ,GPIO_Pin_8);status = 0;}else{GPIO_SetBits(GPIOB ,GPIO_Pin_9);GPIO_SetBits(GPIOB ,GPIO_Pin_8);status = 1;}EXTI_ClearFlag( EXTI_Line0 ); //清理中断标志位}
}
6、串口USART
STM32中配置重映射的情况主要出现在需要对GPIO端口的功能进行改变或重新分配时。每个GPIO都有一组重映射寄存器,用于配置该GPIO端口的重映射方式。当默认引脚不满足某些特定配置要求,如电压、频率等时,可能需要通过重映射来改变引脚的物理位置或功能。
配置重映射的步骤如下:
- 使能AFIO时钟:在使用重映射功能之前,需要先配置AFIO的时钟以使其可用。
- 配置GPIO端口:将源GPIO端口配置为相应的复用功能,以便可以重映射到目标GPIO端口上。
- 配置重映射寄存器:设置重映射寄存器的值,以选择要映射的复用功能和目标GPIO端口。
- 配置目标GPIO端口:将目标GPIO端口配置为相应的复用功能以使用已重映射的信号。
请注意,在进行重映射配置时,必须使能AFIO时钟。另外,虽然有时即使不开启重映射功能也能成功启用重映射引脚并使外设功能正常,但当重映射引脚和默认引脚都使能之后,外设会优先启用默认引脚。
因此,当需要改变GPIO端口的功能或当默认引脚不满足特定配置要求时,STM32就需要配置重映射。具体的配置步骤和注意事项可能因不同的STM32型号和具体应用场景而有所差异,建议查阅相关的STM32参考手册或技术文档以获取更详细和准确的信息。
stm32——串口配置一般步骤_stm32串口配置步骤-CSDN博客
//STM32F051C8TC芯片的RS485通讯
void RS485_initializes(void)
{USART_InitTypeDef USART_InitStructure;GPIO_InitTypeDef GPIO_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); //打开时钟//重映射GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_1); //配置引脚为转换功能GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_1);GPIO_PinAFConfig(GPIOA, GPIO_PinSource12, GPIO_AF_1);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_12;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_Init(GPIOA, &GPIO_InitStructure);USART_OverSampling8Cmd(USART1,ENABLE);USART_InitStructure.USART_BaudRate = 6000000;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(USART1, &USART_InitStructure);/*********************************************/USART_DECmd(USART1,ENABLE); //485方向使能USART_SetDEAssertionTime(USART1,0x1F); //发数据时DE需要提前Tx为高电平,保证数据发送USART_DEPolarityConfig(USART1,USART_DEPolarity_High); //DE极性设置,发送数据为高电平/*********************************************/USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); //开启串口寄存器非空中断USART_Cmd(USART1, ENABLE); //启动USART1USART_ClearFlag(USART1,USART_FLAG_TC); //清楚发送完全标志位置//发数据unsigned short data = 0x20;USART_SendData(USART1 ,data);
6.2、STM32F103C8T6芯片
1、配置USART
void Hardware_USART_Init(void)
{GPIO_InitTypeDef GPIO_InitStructure; //GPIO配置结构体USART_InitTypeDef USART_InitStructure; //USART配置结构体NVIC_InitTypeDef NVIC_InitStructure; //USART中断优先级配置结构体//1、串口时钟使能,GPIO时钟使能RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA ,ENABLE); //打开GPIO时钟,打开USART时钟//2、串口复位USART_DeInit(USART1);
/*****************************************************************//重映射(AFIO)RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO ,ENABLE);GPIO_PinRemapConfig(GPIO_Remap_USART1 ,ENABLE);//USART1_TX 原GPIOA.9是Tx 重映射PB6GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出GPIO_Init(GPIOB, &GPIO_InitStructure); //初始化//USART1_RX 原GPIOA.10Rx 重映射PB7GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空输入GPIO_Init(GPIOB, &GPIO_InitStructure); //初始化
******************************************************************/ //3、配置GPIO为转换功能//USART1_TX 原GPIOA.9是Tx GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化GPIOA.9 //USART1_RX 原GPIOA.10Rx GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //PA10GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空输入GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化GPIOA.10//4、串口参数初始化USART_OverSampling8Cmd(USART1 ,ENABLE); //启用8倍过采样USART_InitStructure.USART_BaudRate = 115200; //波特率USART_InitStructure.USART_WordLength = USART_WordLength_8b; //8位数据位USART_InitStructure.USART_StopBits = USART_StopBits_1; //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); //串口初始化//5、开启中断并初始化NVIC(需要开启中断才需要)NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; //中断源NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //抢占优先级NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //优先级NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //启用中断NVIC_Init(&NVIC_InitStructure); //NVIC初始化//6、使能串口USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); //开启串口寄存器非空中断USART_Cmd(USART1 ,ENABLE); //启动串口USART_ClearFlag(USART1,USART_FLAG_TC); //清除发送完全标志位置
}
2、发送数据
//发送数据
void USART_Print(uint8_t *s) //发送字符串函数
{while(*s){//查USART1模块的发送数据寄存器是否还未准备好(即是否不为空),RESET未准备好while(USART_GetFlagStatus(USART1,USART_FLAG_TXE) == RESET);USART_SendData(USART1,*s);s++;}
}
3、中断方式接收数据
void USART1_IRQHandler(void) //串口1中断服务程序
{volatile unsigned short temp;//1、读数据temp = USART_ReceiveData(USART1); //收//USART_SendData(USART1,temp); //发出去//2、清理FLAGUSART_ClearITPendingBit(USART1,USART_IT_RXNE);
}
7、DMA
STM32 | 串口DMA很难?其实就是如此简单!(超详细、附代码)_stm32串口dma很难?-CSDN博客
#include "hardware_usart.h"#define USART1_MAX_TX_LEN 32 //发送缓存大小,最大USART1_MAX_TX_LEN
#define USART1_MAX_RX_LEN 32unsigned int USART1_TX_BUF[USART1_MAX_TX_LEN]; //发送数据缓存区
unsigned int usart1_rx_buf[USART1_MAX_RX_LEN]; //接收数据缓存区
unsigned int recv_msg[USART1_MAX_RX_LEN]; //复制接收数据去处理void DMA_Config_Tx(void);
void DMA_Config_Rx(void);void Hardware_USART_Init(void)
{GPIO_InitTypeDef GPIO_InitStructure; //GPIO配置结构体USART_InitTypeDef USART_InitStructure; //USART配置结构体NVIC_InitTypeDef NVIC_InitStructure; //USART中断优先级配置结构体//1、串口时钟使能,GPIO时钟使能RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 ,ENABLE); //打开USART时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO ,ENABLE); //打开GPIO时钟,AFIO时钟//2、串口复位USART_DeInit(USART1);//3、配置GPIO为转换功能//USART1_TX GPIOA.9GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9GPIO_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; //PA10GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空输入GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化GPIOA.10//4、串口参数初始化USART_OverSampling8Cmd(USART1 ,ENABLE); //启用8倍过采样USART_InitStructure.USART_BaudRate = 115200; //波特率USART_InitStructure.USART_WordLength = USART_WordLength_8b; //8位数据位USART_InitStructure.USART_StopBits = USART_StopBits_1; //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); //串口初始化//5、开启中断并初始化NVIC(需要开启中断才需要)NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; //中断源NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 8; //抢占优先级NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //优先级NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //启用中断NVIC_Init(&NVIC_InitStructure); //NVIC初始化//6、使能串口USART_ITConfig(USART1, USART_IT_IDLE, ENABLE); //开启串口空闲中断USART_ClearFlag(USART1,USART_FLAG_TC); //清除发送完成标志位置USART_Cmd(USART1 ,ENABLE); //启动串口//配置DMADMA_Config_Tx();DMA_Config_Rx();USART_DMACmd(USART1 ,USART_DMAReq_Tx | USART_DMAReq_Rx ,ENABLE); //启动串口DMA发送和接收}void DMA_Config_Tx(void)
{DMA_InitTypeDef DMA_InitStructure; //DMA配置结构体RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); //打开DMA时钟DMA_DeInit( DMA1_Channel4 ); //DMA通道4(USART1_Tx)复位DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&USART1->DR; //外设地址DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)USART1_TX_BUF; //内存地址DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; //指定数据传输方向,内存到外设DMA_InitStructure.DMA_BufferSize = USART1_MAX_TX_LEN; //缓存区的大小 32字节DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//指定外设地址不变DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //内存寄存器地址增加DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; //指定外设数据宽度(8位)DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; //指定内存数据宽度DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; //工作模式正常,搬完一次数据停在那需要手动再启动DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh; //DMA通道x软件优先级最高DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; //DMA通道x不设置内存到内存传输DMA_ClearFlag(DMA1_FLAG_TC4); //清理DMA传输完成标志DMA_Init(DMA1_Channel4 ,&DMA_InitStructure); //DMA通道x初始化DMA_Cmd(DMA1_Channel4 ,DISABLE); //关闭DMA串口的发送通道
}void DMA_Config_Rx(void)
{DMA_InitTypeDef DMA_InitStructure; //DMA配置结构体RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); //打开DMA时钟DMA_DeInit( DMA1_Channel5 ); //DMA通道5(USART1_Rx)复位DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&USART1->DR; //外设地址DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)usart1_rx_buf; //内存地址DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; //数据传输方向,外设到内存DMA_InitStructure.DMA_BufferSize = USART1_MAX_RX_LEN; //DMA通道缓存区的大小 32字节DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//外设寄存器地址不变DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //内存寄存器地址增加DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; //指定外设数据宽度(8位)DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; //指定内存数据宽度(8位)DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; //工作模式正常DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh; //DMA通道x软件优先级最高DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; //DMA通道x不设置内存到内存传输DMA_ClearFlag(DMA1_FLAG_TC5); //清理DMA传输完成标志DMA_Init(DMA1_Channel5 ,&DMA_InitStructure); //DMA通道x初始化DMA_Cmd(DMA1_Channel5 ,ENABLE); //开启DMA1的5通道
}//USART使用DMA发送数据
void USART_DMA_Tx_Data(unsigned char *buffer)
{ //1、清理标志位TC//DMA_ClearFlag( DMA1_FLAG_TC4 ); //先清理DMA通道4的传输完成标志位//2、关闭DMA1的4通道DMA_Cmd(DMA1_Channel4 ,DISABLE); //因为传输数量寄存器配置需要通道关闭才能配置//3、配置需要发送的数据DMA1_Channel4->CMAR = (uint32_t)buffer;//4、重新设置长度DMA1_Channel4->CCR &= ~(1<<0); //关闭通道DMA1_Channel4->CNDTR = USART1_MAX_TX_LEN; //重新配置传输数量寄存器DMA1_Channel4->CCR |= 1<<0; //开启通道//5、检测DMA传输完成标志位while( SET != DMA_GetFlagStatus(DMA1_FLAG_TC4)); //等待DMA传输完成USART_ClearFlag(USART1 ,USART_FLAG_TC); //清理串口发送完成标志位DMA_ClearFlag(DMA1_FLAG_TC4); //清理DMA传输完成标志}//接收数据
void USART1_IRQHandler(void) //串口1中断服务程序
{uint8_t temp;if ( SET != USART_GetITStatus(USART1 ,USART_FLAG_IDLE)) //触发串口空闲中断,发生返回RESET{//1、关闭通道、拷贝数据DMA_Cmd(DMA1_Channel5 ,DISABLE); //关闭DMA通道//2、重新设置DMA长度DMA1_Channel5->CCR &= ~(1<<0); //关闭通道DMA1_Channel5->CNDTR = USART1_MAX_RX_LEN; //重新配置传输数量寄存器DMA1_Channel5->CCR |= 1<<0; //开启通道//3、清除DMA传输完成标志和串口空闲中断标志temp = USART1->SR;temp = USART1->DR;DMA_ClearFlag( DMA1_FLAG_TC5 );USART_DMA_Tx_Data((unsigned char *)usart1_rx_buf); //接收的数据发送出去}
}
8、TIM
STM32高级定时器TIM1生成互补PWM_stm32 tim1 互补pwm-CSDN博客
STM32之定时器配置-CSDN博客
8.1、TIM+更新中断
void TIMER_INIT(void)
{TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;NVIC_InitTypeDef NVIC_InitStructure;TIM_DeInit(TIM3); //复位定时器/*1、使能TIM2时钟*/RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);/*配置定时2参数 溢出时间 = [ ( TIM_Period + 1 ) * ( TIM_Prescaler + 1 ) / ( SystemCoreClock ) ] ( s )*/TIM_TimeBaseStructure.TIM_Prescaler = 71;/*PSC预分频器,72分频,1MHz*/TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Down;/*向上计数模式*/TIM_TimeBaseStructure.TIM_Period = 499;/*设定计数器的计数值(周期),计数1000次,0.5ms*/TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;/*时钟分频因子*/TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;/*重载周期,高级定时器特有*/TIM_TimeBaseInit(TIM3 ,&TIM_TimeBaseStructure); /*初始化定时器*/TIM_ITConfig(TIM3 ,TIM_IT_Update ,ENABLE); /*启动定时器更新中断*/NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_InitStructure);//TIM_Cmd(TIM3 ,ENABLE); /*开启定时器*/TIM1->CR1 |= 1<<0 ;
}void TIM3_IRQHandler(void)
{static unsigned char flag = 0;if ( RESET == TIM_GetITStatus( TIM3 ,TIM_IT_Update) ) {if (flag == 40){flag = 0;}flag++;if (flag <= 5){GPIO_SetBits(GPIOB ,GPIO_Pin_8); /*输出高电平*/}else{GPIO_ResetBits(GPIOB ,GPIO_Pin_8); /*输出低电平*/}TIM_ClearITPendingBit( TIM3 ,TIM_IT_Update);}
}
8.2、 TIM+PWM
void TIMER_INIT(void)
{TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;GPIO_InitTypeDef GPIO_InitStructure;TIM_OCInitTypeDef TIM_OCInitStructure;//TIM_DeInit(TIM1); //复位定时器/*1、使能TIM1时钟 GPIOA时钟(TIM1_CH2对应PA9)*/RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_TIM1 | RCC_APB2Periph_GPIOB ,ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO ,ENABLE);/*2、配置GPIOA_Pin_9*/GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 ; //配置的引脚 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //配置模式,复用推挽输出GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //速度50MHzGPIO_Init(GPIOA, &GPIO_InitStructure); //配置A组引脚/*配置TIM1_CH2N*/GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14 ; //配置的引脚 GPIO_Init(GPIOB, &GPIO_InitStructure); //配置B组引脚/*3、配置定时1参数(定时) 溢出时间 = [ ( TIM_Period + 1 ) * ( TIM_Prescaler + 1 ) / ( SystemCoreClock ) ] ( s )*/TIM_TimeBaseStructure.TIM_Prescaler = 71;/*PSC预分频器,72分频,1MHz*/TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;/*向上计数模式*/TIM_TimeBaseStructure.TIM_Period = 19999;/*设定计数器的计数值(周期),计数1000次,1ms*/TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;/*时钟分频因子*/TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;/*重载周期,高级定时器特有*/TIM_TimeBaseInit(TIM1 ,&TIM_TimeBaseStructure); /*初始化定时器*//*4、PWM输出定时器1配置,(通道2)*/TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; /*从0递增,小于CCR值为有效.(PWM2于之相反)*/TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; /*使能PWM输出 PA9引脚*/TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Disable; /*开起互补PWM输出 PB14引脚*/TIM_OCInitStructure.TIM_Pulse = 1999; /*配置2ms/20ms = 10%=(CCR+1/ARR+1), CCR=?,ARR=周期*/TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; /*输出极性,高电平*/TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_Low; /*互补输出,有效时为低电平*/TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset; /*输出比较空闲时电平(低电平)*/TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Reset; TIM_OC2Init(TIM1 ,&TIM_OCInitStructure); /*初始化配置的PWM*/ TIM_Cmd(TIM1 ,ENABLE); /*开启定时器*///TIM1->CR1 |= 1<<0 ;/**/TIM_CtrlPWMOutputs( TIM1 ,ENABLE); /*开启PWM输出*/
}