寄存器篇
前言
本文是我学习的一些基础内容的记录(b站:飞熊不熊)。
一、跑马灯
- 时钟配置:
u8 Sys_Clock_Set(u32 plln,u32 pllm,u32 pllp,u32 pllq) { u16 retry=0; u8 status=0; RCC->CR|=1<<16; //HSE 开启 while(((RCC->CR&(1<<17))==0)&&(retry<0X1FFF))retry++;//等待HSE RDY if(retry==0X1FFF)status=1; //HSE无法就绪 else { RCC->APB1ENR|=1<<28; //电源接口时钟使能 PWR->CR|=3<<14; //高性能模式,时钟可到168Mhz RCC->CFGR|=(0<<4)|(5<<10)|(4<<13);//HCLK 不分频;APB1 4分频;APB2 2分频. RCC->CR&=~(1<<24); //关闭主PLL RCC->PLLCFGR=pllm|(plln<<6)|(((pllp>>1)-1)<<16)|(pllq<<24)|(1<<22);//配置主PLL,PLL时钟源来自HSE RCC->CR|=1<<24; //打开主PLL while((RCC->CR&(1<<25))==0);//等待PLL准备好 FLASH->ACR|=1<<8; //指令预取使能. FLASH->ACR|=1<<9; //指令cache使能. FLASH->ACR|=1<<10; //数据cache使能. FLASH->ACR|=5<<0; //5个CPU等待周期. RCC->CFGR&=~(3<<0); //清零 RCC->CFGR|=2<<0; //选择主PLL作为系统时钟 while((RCC->CFGR&(3<<2))!=(2<<2));//等待主PLL作为系统时钟成功. } return status; }
- 时钟介绍:RCC->CFGR|=(0<<4)|(5<<10)|(4<<13);//HCLK 不分频;APB1 4分频;APB2 2分频.
- LED初始化:
//LED IO初始化 void LED_Init(void) { RCC->AHB1ENR|=1<<5;//使能PORTF时钟 GPIO_Set(GPIOF,PIN9|PIN10,GPIO_MODE_OUT,GPIO_OTYPE_PP,GPIO_SPEED_100M,GPIO_PUPD_PU); //PF9,PF10设置 LED0=1;//LED0关闭 LED1=1;//LED1关闭 }
- 实现:
int main(void) { Stm32_Clock_Init(336,8,2,7);//设置时钟,168Mhz delay_init(168); //初始化delay函数 LED_Init(); //初始化LED时钟 while(1) { LED0=0; //亮 LED1=1; //灭 delay_ms(200); LED0=1; //灭 LED1=0; //亮 delay_ms(200); } }
5.电路原理:所以当PA6/PA7为低电平时亮(LEDx为0时LED亮)
二、蜂鸣器
1.引脚配置
//BEEP IO初始化
void BEEP_Init(void)
{
RCC->AHB1ENR|=1<<5; //使能PORTF时钟
GPIO_Set(GPIOF,PIN8,GPIO_MODE_OUT,GPIO_OTYPE_PP,GPIO_SPEED_100M,GPIO_PUPD_PD); //PF8设置,下拉
BEEP=0; //关闭蜂鸣器
}
2.电路原理
蜂鸣器电路:
分析:R59为限流电阻,R61为下拉电阻。当BEEP=1时,三极管导通,蜂鸣器响,BEEP=0时,三极管不导通,蜂鸣器不响。
三、按键
1.引脚配置:
//按键初始化函数
void KEY_Init(void)
{
RCC->AHB1ENR|=1<<0; //使能PORTA时钟
RCC->AHB1ENR|=1<<4; //使能PORTE时钟
GPIO_Set(GPIOE,PIN2|PIN3|PIN4,GPIO_MODE_IN,0,0,GPIO_PUPD_PU); //PE2~4设置上拉输入
GPIO_Set(GPIOA,PIN0,GPIO_MODE_IN,0,0,GPIO_PUPD_PD); //PA0设置为下拉输入
}
2.实现:
首先是去抖动(20ms以内),这里选择10ms,然后判断按键是否连按,以及根据按键引脚输入信号来判断按下的是哪个按键,最后输出按键所对应的数值。(优先级,KEY0>KEY1>KEY2>KEY_UP,原因:代码中书写的先后顺序决定)
u8 KEY_Scan(u8 mode)
{
static u8 key_up=1;//按键按松开标志
if(mode)key_up=1; //支持连按
if(key_up&&(KEY0==0||KEY1==0||KEY2==0||WK_UP==1))
{
delay_ms(10);//去抖动
key_up=0;
if(KEY0==0)return 1;
else if(KEY1==0)return 2;
else if(KEY2==0)return 3;
else if(WK_UP==1)return 4;
}else if(KEY0==1&&KEY1==1&&KEY2==1&&WK_UP==0)key_up=1;
return 0;// 无按键按下
}
3.电路原理:
首先就是电平触发方式的不同,WK_UP高电平触发,其它低电平触发,接着就是引脚接收的代码,使用sys.h中定义的:PEin(n) BIT_ADDR(GPIOE_IDR_Addr,n) //输入,来接收引脚输入信号。
四、串口
1.引脚设置:
首先先配置引脚以及串口时钟,接着配置串口1RX、TX引脚的复用,引脚复用为串口1(USART1),设置串口参数,如波特率等,开启串口中断。
void uart_init(u32 pclk2,u32 bound)
{
float temp;
u16 mantissa;
u16 fraction;
temp=(float)(pclk2*1000000)/(bound*16);//得到USARTDIV@OVER8=0
mantissa=temp; //得到整数部分
fraction=(temp-mantissa)*16; //得到小数部分@OVER8=0
mantissa<<=4;
mantissa+=fraction;
RCC->AHB1ENR|=1<<0; //使能PORTA口时钟
RCC->APB2ENR|=1<<4; //使能串口1时钟
GPIO_Set(GPIOA,PIN9|PIN10,GPIO_MODE_AF,GPIO_OTYPE_PP,GPIO_SPEED_50M,GPIO_PUPD_PU);//PA9,PA10,复用功能,上拉输出
GPIO_AF_Set(GPIOA,9,7); //PA9,AF7
GPIO_AF_Set(GPIOA,10,7);//PA10,AF7
//波特率设置
USART1->BRR=mantissa; //波特率设置
USART1->CR1&=~(1<<15); //设置OVER8=0
USART1->CR1|=1<<3; //串口发送使能
#if EN_USART1_RX //如果使能了接收
//使能接收中断
USART1->CR1|=1<<2; //串口接收使能
USART1->CR1|=1<<5; //接收缓冲区非空中断使能
MY_NVIC_Init(3,3,USART1_IRQn,2);//组2,最低优先级
#endif
USART1->CR1|=1<<13; //串口使能
}
2.代码原理:设置PCLK2时钟频率为84,因为APB2是系统时钟频率的2分频,也就是168/2=84(MHz),设置波特率为115200 bits/s(位/秒,也就是波特)
uart_init(84,115200); //串口初始化,波特率为115200
3.串口数据的接收和发送:
串口是全双工的,所以可以同时收发(全双工的输入和输出可同时进行,半双工则不能同时进行),引脚分别为发送端TX和接收端RX。串口接收数据的代码和解释如下:
if(USART1->SR&(1<<5)) // 检查USART1->SR寄存器的第5位是否为1,即判断是否接收到数据
{
res=USART1->DR; // 将接收到的数据存储在res变量中
if((USART_RX_STA&0x8000)==0) // 判断接收状态是否未完成,即判断USART_RX_STA的最高位是否为0
{
if(USART_RX_STA&0x4000) // 判断是否接收到了0x0d
{
if(res!=0x0a) // 判断接收到的数据是否为0x0a
USART_RX_STA=0; // 如果不是,表示接收错误,将接收状态置为0,重新开始接收数据
else
USART_RX_STA|=0x8000; // 如果是,表示接收完成,将接收状态最高位置为1,表示接收完成
}
else // 如果还未收到0X0D
{
if(res==0x0d)
USART_RX_STA|=0x4000; // 如果接收到的数据为0x0d,将接收状态第14位置为1,表示接收到了0x0d
else
{
USART_RX_BUF[USART_RX_STA&0X3FFF]=res; // 将接收到的数据存储在接收缓冲区中
USART_RX_STA++; // 接收状态加1
if(USART_RX_STA>(USART_REC_LEN-1))
USART_RX_STA=0; // 如果接收状态超过了缓冲区长度,表示接收数据错误,将接收状态置为0,重新开始接收数据
}
}
}
}
目录
三、按键
四、串口
总结
总结
以上就是我在学习中所记录的内容,本文仅仅简单介绍了我学习中的程序原理以及代码,如果有错误的地方,希望能指出、交流一下正确答案,感谢你的浏览,希望这些对你有所帮助(b站:飞熊不熊)。