系列索引《嵌入式系统》 | 嵌入式系统 重点知识梳理
所有GPIO引脚,使用前必须先打开其所属端口时钟。
常用库函数
GPIO_Init:根据GPIO_InitStruct中指定的参数初始化GPIOx端口;
GPIO_SetBits:将指定的GPIO端口的一个或多个指定引脚置位;
GPIO_ResetBits: 将指定的GPIO端口的一个或多个指定引脚复位;
GPIO_ReadOutputDataBit:读取指定GPIO端口的指定引脚的输出值(1 bit);
GPIO_ReadInputDataBit:读取指定GPIO端口的指定引脚的输入值(1 bit);
初始化连接LED0的PA8引脚
——打开APB2总线上GPIOA端口的时钟
/* Enable GPIO_LED0 clock */
RCC_APB2PeriphClockCmd(
RCC_APB2Periph_GPIOA,
ENABLE);
初始化连接LED0的PA8引脚
——将PA8引脚设置为推挽输出模式
/* GPIO_LED0 Pin(PA8) Configuration */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
开启或关闭LED灯
LED_On(void){
GPIO_ResetBits(GPIOA,GPIO_Pin_8)
}
LED_Off(void){
GPIO_SetBits(GPIOA,GPIO_Pin_8)
}
初始化连接按键KEY0的PC5引脚
——打开APB2总线上GPIOC端口的时钟
/* Enable GPIO_KEY0 clock */
RCC_APB2PeriphClockCmd(
RCC_APB2Periph_GPIOC,
ENABLE);
初始化连接按键KEY0的PC5引脚
——将PC5引脚设置为输入上拉模式
/* GPIO_KEY0 Pin(PC5) Configuration */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure);
检测按键输入key0
Unsigned int Key0_Read(void){
if(!GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_5))
return 1;
else
return 0;
}
GPIO设置-void key_Init_Row(void)
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(KEY_ROW_GPIO_CLK,ENABLE);//使能时钟
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;//通用推挽输出
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Pin=KEY_ROW_GPIO_PIN1|KEY_ROW_GPIO_PIN2|KEY_ROW_GPIO_PIN3|KEY_ROW_GPIO_PIN4;
GPIO_Init(KEY_ROW_GPIO_PORT,&GPIO_InitStructure);
#define KEY_ROW_GPIO_CLK RCC_APB2Periph_GPIOE
#define KEY_ROW_GPIO_PORT GPIOE
GPIO设置
RCC_APB2PeriphClockCmd(KEY_LIST_GPIO_CLK,ENABLE);//使能时钟
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPD; //下拉输入
GPIO_InitStructure.GPIO_Pin=KEY_LIST_GPIO_PIN1|KEY_LIST_GPIO_PIN2|KEY_LIST_GPIO_PIN3|KEY_LIST_GPIO_PIN4;
GPIO_Init(KEY_LIST_GPIO_PORT,&GPIO_InitStructure);
GPIO_SetBits(KEY_ROW_GPIO_PORT,KEY_ROW_GPIO_PIN1|KEY_ROW_GPIO_PIN2|KEY_ROW_GPIO_PIN3|KEY_ROW_GPIO_PIN4); //将引脚置为高电平
#define KEY_LIST_GPIO_CLK RCC_APB2Periph_GPIOF
#define KEY_LIST_GPIO_PORT GPIOF
按键扫描
if(GPIO_ReadInputDataBit(KEY_LIST_GPIO_PORT,KEY_LIST_GPIO_PIN1)==1)
{
SysTick_Delay_ms(10); //软件“消抖”
if(GPIO_ReadInputDataBit(KEY_LIST_GPIO_PORT,KEY_LIST_GPIO_PIN1)==1)
{
key_Init_List();
if(GPIO_ReadInputDataBit(KEY_ROW_GPIO_PORT,KEY_ROW_GPIO_PIN1)==1)
return 1;
else if(GPIO_ReadInputDataBit(KEY_ROW_GPIO_PORT,KEY_ROW_GPIO_PIN2)==1)
return 4;
else if(GPIO_ReadInputDataBit(KEY_ROW_GPIO_PORT,KEY_ROW_GPIO_PIN3)==1)
return 7;
else if(GPIO_ReadInputDataBit(KEY_ROW_GPIO_PORT,KEY_ROW_GPIO_PIN4)==1)
return '*';
}
}
TIM_TimeBaseInit:根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx。
TIM_OC1Init:根据TIM_OCInitStruct中指定的参数初始化外设 TIMx的通道1。
TIM_OC2Init:根据TIM_OCInitStruct中指定的参数初始化外设 TIMx的通道2。
TIM_OC3Init:根据TIM_OCInitStruct中指定的参数初始化外设 TIMx的通道3。
TIM_OC4Init:根据TIM_OCInitStruct中指定的参数初始化外设 TIMx的通道4。
TIM_OC1PreloadConfig:使能或者禁止TIMx在CCR1上的预装载寄存器。
TIM_OC2PreloadConfig:使能或者禁止TIMx在CCR2上的预装载寄存器。
TIM_OC3PreloadConfig:使能或者禁止TIMx在CCR3上的预装载寄存器。
TIM_OC4PreloadConfig:使能或者禁止TIMx在CCR4上的预装载寄存器。
TIM_ARRPreloadConfig:使能或者禁止TIMx在ARR上的预装载寄存器。
TIM_CtrlPWMOutputs:使能或禁止TIMx的主输出。
TIM_Cmd:使能或者禁止TIMx。
初始化输入捕获通道。调用函数:TIM_ICInit();
TIM_GetFlagStatus:检查指定的TIMx标志位的状态。
TIM_ClearFlag:清除 TIMx 的待处理标志位。
TIM_ITConfig:使能或者禁止指定的TIMx中断。
TIM_GetITStatus:检查指定的TIMx中断是否发生。
TIM_ClearITPendingBit:清除TIMx的中断挂起位。
delay_init()
首先是delay_init(),延时初始化函数。利用Syst_CLKSourceConfig()函数选择SysTick时钟源,选择外部时钟(HCLK的1/8);同时初始化fac_us和fac_ms两个变量。
void delay_init()
{
SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8); //选择外部时钟 HCLK/8
fac_us=SystemCoreClock/8000000; //为系统时钟的1/8,实际上也就是在计算1usSysTick的VAL减的数目
fac_ms=(u16)fac_us*1000; //代表每个ms需要的systick时钟数,即每毫秒SysTick的VAL减的数目
}
delay_ms()
其次,delay_ms(),此函数用来延时指定的ms。
此时要注意nms的范围,SysTick->LOAD为24位寄存器,所以最大延时为:nms<=0xffffff81000/SYSCLK;SYSCLK单位为Hz,nms单位为ms。对72M条件下,nms<=1864。如果超出这个值,建议多次调用此函数来实现。
void delay_ms(u16 nms)
{
u32 temp;
SysTick->LOAD=(u32)nms*fac_ms; //时间加载(SysTick->LOAD为24bit)
SysTick->VAL =0x00; //清空计数器
SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ; //开始倒数
do
{
temp=SysTick->CTRL;
}while((temp&0x01)&&!(temp&(1<<16))); //等待时间到达,看CTRL的第16位(COUNTFLAG)是否为1,看STRL的第0位(ENABLE)是否为1
SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk; //关闭计数器
SysTick->VAL =0X00; //清空计数器
}
这段代码其实就是先把延时的时间换算成SysTick的时钟周期数,然后写入LOAD寄存器。然后清空当前寄存器VAL的内容,再开启倒数功能。等倒数结束即延时了nms、最后关闭SysTick,清空VAL的值,实现一次延时的操作。
这里特别说一下,temp&0x01,这一句用来判断SysTick定时器是否还处在开启的状态,可以防止SysTick被意外关闭导致的死循环。
delay_us()
最后,delay_us(),此函数用来延时指定的us。具体的逻辑和上面一个函数类似,就不介绍了。
void delay_us(u32 nus)
{
u32 temp;
SysTick->LOAD=nus*fac_us; //时间加载
SysTick->VAL=0x00; //清空计数器
SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ; //开始倒数
do
{
temp=SysTick->CTRL;
}while((temp&0x01)&&!(temp&(1<<16))); //等待时间到达
SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk; //关闭计数器
SysTick->VAL =0X00; //清空计数器
}
delay延时的相关函数在SYSTEM文件夹下的delay子文件夹,在使用delay_ms()或者delay_us()函数之前一定不要忘记先初始化delay_init()。
设定时间为10:15:30
/*初始化RTC RTC_Configuration() */
void RTC_Configuration(void)
{
/*使能PWR和BKP时钟*/
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);
/*取消备份区写保护*/
PWR_BackupAccessCmd(ENABLE);
BKP_DeInit();
/* 使能低速外部时钟 LSE */
RCC_LSEConfig(RCC_LSE_ON);
while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET)
{} //等待LSE起振稳定
/* 选择LSE作为 RTC 外设的时钟*/
RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);
RCC_RTCCLKCmd(ENABLE); // 使能RTC时钟
/* 等待RTC寄存器与APB1同步*/
RTC_WaitForSynchro();
RTC_WaitForLastTask();
/* 设置RT 时钟分频: 使RTC定时周期为1秒 */
RTC_SetPrescaler(32767); // RTC 周期 = RTCCLK/RTC_PR = (32.768 KHz)/(32767+1)
RTC_WaitForLastTask(); //等待对RTC的写操作完成
/*配置时钟*/
RTC_SetCounter(36930); //36930=10*3600+15*60+30 10:15:30
RTC_WaitForLastTask();
/*记录信息,使能中断*/
BKP_WriteBackupRegister(BKP_DR1,0x5858);
RTC_ITConfig(RTC_IT_SEC, ENABLE);
RTC_WaitForLastTask();
}
NVIC_DeInit:将NVIC的寄存器恢复为复位启动时的默认值。
NVIC_PriorityGroupConfig:设置优先级分组。
NVIC_Init:根据NVIC_InitStruct中指定的参数初始化NVIC。
设置中断优先级
/* Configure one bit for preemption priority */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);//设置中断优先级组
/* Enable the TIM2_IRQn Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; //设置TIM2_IRQn中断通道
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; // 指定抢占式优先级别,可取0-7
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //子优先级为0
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器
编写对应的中断服务程序
DMA_DeInit:将DMAy的通道x的寄存器恢复为复位启动时的默认值。
DMA_Init:根据DMA_InitStruct中指定的参数初始化指定DMA通道的寄存器。
DMA_GetCurrDataCounter:返回当前指定DMA通道剩余的待传输数据数目。
DMA_Cmd:使能或者禁止指定的DMA通道。
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);
DMA_GetFlagStatus:查询指定的DMA通道的标志位状态。
DMA_ClearFlag:清除指定的DMA通道的待处理标志位。
DMA_ITConfig:使能或禁止指定的DMA通道中断。
DMA_GetITStatus:查询指定DMAy的通道x的中断的状态。
DMA_ClearITPendingBit:清除DMAy的通道x的中断挂起位。
ADC开始转换、结束转换和结果读取
USART_DeInit:将USARTx的寄存器恢复为复位启动时的默认值。
USART_Init:根据USART_InitStruct中指定的参数初始化指定USART的寄存器。
USART_Cmd:使能或禁止指定USART。
USART_SendData:通过USART发送单个数据。
USART_ReceiveData:返回指定USART最近接收到的数据。
USART_GetFlagStatus:查询指定USART的标志位状态。
USART_ClearFlag:清除指定USART的标志位。
USART_ITConfig:使能或禁止指定的USART中断。
USART_GetITStatus:查询指定的USART中断是否发生。
USART_ClearITPendingBit:清除指定的USART中断挂起位。
SPI_I2S_DeInit:将SPIx的寄存器恢复为复位启动时的默认值。
SPI_Init:根据SPI_InitStruct中指定的参数初始化指定SPI的寄存器。
SPI_Cmd:使能或禁止指定SPI。
SPI_I2S_SendData:通过SPI/I2S发送单个数据。
SPI_I2S_ReceiveData:返回指定SPI/I2S最近接收到的数据。
SPI_I2S_GetFlagStatus:查询指定SPI/I2S的标志位状态。
SPI_I2S_ClearFlag:清除指定SPI/I2S的标志位(SPI_FLAG_CRCERR)。
SPI_I2S_ITConfig:使能或禁止指定的SPI/I2S中断。
SPI_I2S_GetITStatus:查询指定的SPI/I2S中断是否发生。
SPI_I2S_ClearITPendingBit:清除指定的SPI/I2S中断挂起位(SPI_IT_CRCERR)。
I2C_DeInit:将I2Cx的寄存器恢复为复位启动时的默认值。
I2C_Init:根据I2C_InitStruct中指定的参数初始化指定I2C的寄存器。
I2C_Cmd:使能或禁止指定I2C。
I2C_GenerateSTART:产生I2Cx传输的起始信号。
I2C_Send7bitAddress:发送地址信息来选中指定的I2C从设备。
I2C_SendData:通过I2C发送单字节数据。
I2C_ReceiveData:返回指定I2C最近接收到的字节数据。
I2C_CheckEvent:查询I2Cx最近一次发生的事件是否是I2C_EVENT指定的事件。
I2C_AcknowledgeConfig:使能或者禁止指定I2C的应答功能。
I2C_GenerateSTOP:产生I2Cx传输的结束信号。
I2C_GetFlagStatus:查询指定I2C的标志位状态。
I2C_ClearFlag:清除指定I2C的标志位。
I2C_ITConfig:使能或禁止指定的I2C中断。
I2C_GetITStatus:查询指定的I2C中断是否发生。
I2C_ClearITPendingBit:清除指定的I2C中断请求挂起位。
I2C_DMACmd:使能或禁止指定I2C的DMA请求。