国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

STM32基礎(chǔ)入門學(xué)習(xí)筆記:核心板 電路原理與驅(qū)動(dòng)編程

這篇具有很好參考價(jià)值的文章主要介紹了STM32基礎(chǔ)入門學(xué)習(xí)筆記:核心板 電路原理與驅(qū)動(dòng)編程。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

文章目錄:

一:LED燈操作?

1.LED燈的點(diǎn)亮和熄滅 延遲閃爍

main.c?

led.c

led.h

BitAction枚舉

2.LED呼吸燈(燈的強(qiáng)弱交替變化)

main.c?

delay.c

3.按鍵控制LED燈

key.h

key.c

main.c?

二:FLASH讀寫程序(有記憶可以保存斷電之前的狀態(tài))

flash.h

flash.c

main.c

flash操作注意事項(xiàng)

三:蜂鳴器驅(qū)動(dòng)程序(按鍵有聲音)

buzzer.h

buzzer.c

main.c

四:MIDI音樂播放程序(基于蜂鳴器)

buzzer.c

buzzer.h

main.c

五:USART串口通信驅(qū)動(dòng)程序(串口助手 超級(jí)終端)

1.USART發(fā)送程序(3種方法)

usart.h

usart.c

main.c

2.USART接收程序(2種方法)

2.1 查詢方式接收數(shù)據(jù)?

main.c

2.2 中斷方式接收數(shù)據(jù)

usart.c

3.USART串口控制程序(雙向交互):通過串口助手控制LED燈的開關(guān)狀態(tài)和蜂鳴器、在單片機(jī)中按鍵操作在串口助手中進(jìn)行顯示

main.c

4.超級(jí)終端串口遠(yuǎn)程控制LED程序(命令行操作形式)

usart.h

usart.c????????

mian.c

六:RTC實(shí)時(shí)時(shí)鐘原理驅(qū)動(dòng)程序

1.基于RTC的LED走時(shí)驅(qū)動(dòng)程序(BKP備用寄存器)?

rtc.h

rtc.c

main.c

2.RTC超級(jí)終端串口顯示日歷程序(命令行操作形式)

usart.c

main.c

七:RCC時(shí)鐘復(fù)位和設(shè)置程序

rtc.c

mian.c

led.c


STM32基礎(chǔ)入門學(xué)習(xí)筆記:核心板 電路原理與驅(qū)動(dòng)編程,# STM32,學(xué)習(xí),筆記

?STM32基礎(chǔ)入門學(xué)習(xí)筆記:核心板 電路原理與驅(qū)動(dòng)編程,# STM32,學(xué)習(xí),筆記

區(qū)別:秒s、毫秒ms、微秒μs、納秒ns、皮秒ps、飛秒fs每兩級(jí)之間的換算以及之間的關(guān)系_ps和fs區(qū)別

區(qū)別:千赫kHz、兆赫MHz、吉赫GHz、太赫THz、拍赫PHz、艾赫EHz每兩級(jí)之間的換算以及之間的關(guān)系_太赫茲與ghz

一:LED燈操作?

1.LED燈的點(diǎn)亮和熄滅 延遲閃爍

原理:輸出高低電平控制

main.c?

#include "stm32f10x.h"
#include "sys.h"
#include "delay.h"
#include "led.h"


int main (void){//主程序
	RCC_Configuration(); //時(shí)鐘設(shè)置
	LED_Init();
	while(1){
		
		//方法1:采用枚舉(BitAction)(1)    GPIO_WriteBit設(shè)置或者清除指定的數(shù)據(jù)端口位(端口組、端口名、位控制)
		GPIO_WriteBit(LEDPORT,LED1,(BitAction)(1)); //LED1接口輸出高電平1
		delay_ms(500); //延時(shí)0.5秒
		GPIO_WriteBit(LEDPORT,LED1,(BitAction)(0)); //LED1接口輸出低電平0
		delay_ms(500); //延時(shí)0.5秒
		
    	//方法2:取IO口當(dāng)前狀態(tài)            GPIO_ReadOutputDataBit —— 讀取端口輸出值
		GPIO_WriteBit(LEDPORT,LED1,(BitAction)(1-GPIO_ReadOutputDataBit(LEDPORT,LED1))); //取反LED1
		delay_ms(1000); //延時(shí)1秒

   	    //方法3:直接設(shè)置IO口              GPIO_SetBits設(shè)置指定的數(shù)據(jù)端口位(端口組、端口名)
		GPIO_SetBits(LEDPORT,LED1); //LED燈都為高電平(1)
		delay_s(1); //延時(shí)1秒
		GPIO_ResetBits(LEDPORT,LED1); //LED燈都為低電平(0)
		delay_s(1); //延時(shí)1秒

		//方法4:對(duì)_ IO 組_ 的數(shù)值寫入     GPIO_Write向指定GPIO數(shù)據(jù)端口整組寫入數(shù)據(jù)(端口清零置1)
		GPIO_Write(LEDPORT,0x0001); //直接數(shù)值操作將變量值寫入LED
		delay_s(2); //延時(shí)1秒
		GPIO_Write(LEDPORT,0x0000); //直接數(shù)值操作將變量值寫入LED
		delay_s(2); //延時(shí)1秒

        //方法5:直接控制端口。PB(1)=1;PB1端口直接賦值
	}
}

led.c

#include "led.h"       //導(dǎo)入自己編寫的 led.h的頭文件,里面有許多自己宏定義的成員(變量)和函數(shù)

void LED_Init(void){											 //LED燈的接口初始化
   GPIO_InitTypeDef  GPIO_InitStructure; 	
   RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOC,ENABLE);      //高速總線apb2上啟動(dòng)gpio a/b/c       

   GPIO_InitStructure.GPIO_Pin = LED1 | LED2; 					//選擇端口號(hào)(0~15或all)              可以使用宏定義名在led.h查看引腳                        
   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 			//選擇IO接口工作方式                   GPIO推挽方式輸出   
   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 			//設(shè)置IO接口速度(2/10/50MHz)         只有io被設(shè)置為輸出時(shí)才配置速度

   GPIO_Init(LEDPORT, &GPIO_InitStructure);		                //將配置的結(jié)構(gòu)體內(nèi)容寫入到ledport-gpiob那一組端口當(dāng)中	
}

led.h

#ifndef __LED_H 
#define __LED_H	 
#include "sys.h"

//#define LED1 PBout(0)// PB0   也可以直接用這   <-容易理解
//#define LED2 PBout(1)// PB1	
#define LEDPORT	GPIOB	//定義IO接口  <- 優(yōu)點(diǎn)是移植方便 ,越到后面越需要這樣編譯
#define LED1	GPIO_Pin_0	//定義IO接口
#define LED2	GPIO_Pin_1	//定義IO接口

void LED_Init(void);      //LED的初始化函數(shù)聲明 ,就不用再從.c程序中聲明
	 				    
#endif

BitAction枚舉

typedef enum
{
    Bit_REST = 0;
    Bit_SET; //默認(rèn)為1這里
}BitAction;

2.LED呼吸燈(燈的強(qiáng)弱交替變化)

原理:調(diào)節(jié)LED燈點(diǎn)亮和熄滅時(shí)間的比例、呼吸燈的速度來控制?

main.c?

#include "stm32f10x.h" //STM32頭文件
#include "sys.h"
#include "delay.h"

#include "led.h"

int main (void){//主程序
	//定義需要的變量
	u8 MENU; //菜單模式		8位無符號(hào)
	u16 t,i;	//16位無符號(hào)
	RCC_Configuration(); //時(shí)鐘設(shè)置

	LED_Init();//led初始化
	MENU=0;	 //初始菜單狀態(tài)
	t=1;   //初始亮狀態(tài)延時(shí)時(shí)長
	//主循環(huán)
	while(1){
		//菜單0	  根據(jù)菜單的值不同運(yùn)行不同的程序
		if(MENU==0)
		{
			for(i=0;i<10;i++)//由于延時(shí)時(shí)間t從0~500 所以是循環(huán)變亮	   i的值可以調(diào)節(jié)呼吸燈變化的速度
			{//同一個(gè)亮度循環(huán)10次
				GPIO_WriteBit(LEDPORT,LED1,(BitAction)(1));//LED1接口輸出高電平1
				    delay_us(t);	
				GPIO_WriteBit(LEDPORT,LED1,(BitAction)(0));//LED1接口輸出高電平1
				    delay_us(501-t);	 //通過將501換成更大的值可以將亮度細(xì)分為更多的等級(jí)
			}
			t++;
			if(t==500){//由亮變暗
				MENU=1;
			}
		}
		//菜單1
		if(MENU==1)
		{
			for(i=0;i<10;i++)//由于延時(shí)時(shí)間t從500~0 所以是循環(huán)變暗
			{
				GPIO_WriteBit(LEDPORT,LED1,(BitAction)(1));//LED1接口輸出高電平1
				delay_us(t);	
				GPIO_WriteBit(LEDPORT,LED1,(BitAction)(0));//LED1接口輸出高電平1
				delay_us(501-t);	
			}
			t--;
			if(t==1){
				MENU=0;
			}
		}
	}
}

delay.c

#include "delay.h"

#define AHB_INPUT  72                   //請(qǐng)按RCC中設(shè)置的AHB時(shí)鐘頻率填寫到這里(單位MHz)

void delay_us(u32 uS)
{                                       //uS微秒級(jí)延時(shí)程序(參考值即是延時(shí)數(shù),72MHz時(shí)最大值233015)	
	SysTick->LOAD=AHB_INPUT*uS;         //重裝計(jì)數(shù)初值(當(dāng)主頻是72MHz,72次為1微秒)
	SysTick->VAL=0x00;                  //清空定時(shí)器的計(jì)數(shù)器
	SysTick->CTRL=0x00000005;           //時(shí)鐘源HCLK,打開定時(shí)器
	while(!(SysTick->CTRL&0x00010000)); //等待計(jì)數(shù)到0
	SysTick->CTRL=0x00000004;           //關(guān)閉定時(shí)器
}

3.按鍵控制LED燈

原理:通過讀取按鍵端口輸入進(jìn)行控制

key.h

#ifndef __KEY_H
#define __KEY_H	 
#include "sys.h"

//#define KEY1 PAin(0)// PA0
//#define KEY2 PAin(1)// PA1

#define KEYPORT	GPIOA	//定義IO接口組
#define KEY1	GPIO_Pin_0	//定義IO接口
#define KEY2	GPIO_Pin_1	//定義IO接口


void KEY_Init(void);//聲明按鍵初始化

		 				    
#endif

key.c

#include "key.h"

void KEY_Init(void)//微動(dòng)開關(guān)的接口初始化
{ 
	GPIO_InitTypeDef  GPIO_InitStructure; //定義GPIO的初始化枚舉結(jié)構(gòu)	

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);       

    GPIO_InitStructure.GPIO_Pin = KEY1 | KEY2; //選擇端口號(hào)(0~15或all)                        
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //選擇IO接口工作方式 //上拉電阻       
    //GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //設(shè)置IO接口速度,屏蔽掉了,輸入時(shí)不需要速度配置(2/10/50MHz)    

	GPIO_Init(KEYPORT,&GPIO_InitStructure);//此時(shí)才把io的配置進(jìn)行初始化?。?!		
}

main.c?

#include "stm32f10x.h" //STM32頭文件
#include "sys.h"
#include "delay.h"
#include "led.h"

#include "key.h" 

int main (void){//主程序
	//初始化程序
	RCC_Configuration(); //時(shí)鐘設(shè)置
	LED_Init();//LED初始化

	KEY_Init();//按鍵初始化

	//主循環(huán)
	while(1){//GPIO_ReadInputDataBit —— 讀取端口輸入

		//示例1:無鎖存    按著亮,松開熄滅
		    if(GPIO_ReadInputDataBit(KEYPORT,KEY1)){ //讀按鍵接口的電平
			    GPIO_ResetBits(LEDPORT,LED1); //LED燈都為低電平(0) 
		        }else{	
        	    GPIO_SetBits(LEDPORT,LED1); //LED燈都為高電平(1) 
		    }
		    if(GPIO_ReadInputDataBit(KEYPORT,KEY2)){ //讀按鍵接口的電平
			    GPIO_ResetBits(LEDPORT,LED2); //LED燈都為低電平(0) 
		    }else{	
        	    GPIO_SetBits(LEDPORT,LED2); //LED燈都為高電平(1) 
		    }
		//示例2:無鎖存
		GPIO_WriteBit(LEDPORT,LED1,(BitAction)(!GPIO_ReadInputDataBit(KEYPORT,KEY1))); 

		//示例3:有鎖存    第一次按燈亮,松開還是亮,第二次按熄滅
		if(!GPIO_ReadInputDataBit(KEYPORT,KEY1)){ //讀按鍵接口的電平
			delay_ms(20); //延時(shí)去抖動(dòng)
			if(!GPIO_ReadInputDataBit(KEYPORT,KEY1)){ //讀按鍵接口的電平
				GPIO_WriteBit(LEDPORT,LED1,(BitAction)(1-GPIO_ReadOutputDataBit(LEDPORT,LED1))); //LED取反
				while(!GPIO_ReadInputDataBit(KEYPORT,KEY1)); //等待按鍵松開 
			}
		}

		//示例4:有鎖存    按第一次第一個(gè)燈亮,按第二次第一個(gè)燈熄滅第二個(gè)燈亮,按第三次亮燈亮,第四次按同時(shí)熄滅
		if(!GPIO_ReadInputDataBit(KEYPORT,KEY1)){ //讀按鍵接口的電平
			delay_ms(20); //延時(shí)20ms去抖動(dòng)
			if(!GPIO_ReadInputDataBit(KEYPORT,KEY1)){ //讀按鍵接口的電平
				//在2個(gè)LED上顯示二進(jìn)制加法
				a++; //變量加1
				if(a>3){ //當(dāng)變量大于3時(shí)清0
					a=0; 
				}
				GPIO_Write(LEDPORT,a); //直接數(shù)值操作將變量值寫入LED(LED在GPIOB組的PB0和PB1上)
                                       //以a的值賦給端口組,實(shí)現(xiàn) “僅D1亮、僅D2亮、都亮、都滅” 的循環(huán)
                                       //                          0       1       2     3
				while(!GPIO_ReadInputDataBit(KEYPORT,KEY1)); //等待按鍵松開 
			}
		}

	}
}

二:FLASH讀寫程序(有記憶可以保存斷電之前的狀態(tài))

原理:通過在指定頁擦除和指定地址寫入數(shù)據(jù)進(jìn)行控制?

如何把存儲(chǔ)數(shù)據(jù)到FLASH中?

在Basic文件夾中——>創(chuàng)建一個(gè)FLASH文件夾(flash.c flash.h)


注意查看lib文件夾下的flash.c是否存在

flash.h

#ifndef __FLASH_H
#define __FLASH_H 			   
#include "sys.h"

#define LEDPORT	GPIOB	//定義IO接口  <- 優(yōu)點(diǎn)是移植方便 ,越到后面越需要這樣編譯
#define KEY1	GPIO_Pin_0	//定義IO接口
#define KEY2	GPIO_Pin_1	//定義IO接口

void LED_Init(void);      //LED的初始化函數(shù)聲明 ,就不用再從.c程序中聲明
void KEY_Init(void);      //聲明按鍵初始化


void FLASH_W(u32 add,u16 dat);
//void FLASH_W(u32 add,u16 dat,u16 dat2);多個(gè)情況;若果過多可以使用數(shù)組或指針來解決
u16 FLASH_R(u32 add);

#endif

flash.c

#include "flash.h"http://導(dǎo)入頭文件

//FLASH寫入數(shù)據(jù)
void FLASH_W(u32 add,u16 dat){ //參數(shù)1:32位FLASH地址。參數(shù)2:16位數(shù)據(jù)
//void FLASH_W(u32 add,u16 dat,u16 dat2){//多個(gè)情況
    //	 RCC_HSICmd(ENABLE); //打開HSI時(shí)鐘
	 FLASH_Unlock();  //解鎖FLASH編程擦除控制器

     FLASH_ClearFlag(FLASH_FLAG_BSY|FLASH_FLAG_EOP|FLASH_FLAG_PGERR|FLASH_FLAG_WRPRTERR);//清除標(biāo)志位

     FLASH_ErasePage(add);               //擦除指定地址頁
     FLASH_ProgramHalfWord(add,dat);     //從指定頁的addr地址寫入
     //FLASH_ProgramHalfWord(add+1,dat2);//多個(gè)情況(是加上這條)

     FLASH_ClearFlag(FLASH_FLAG_BSY|FLASH_FLAG_EOP|FLASH_FLAG_PGERR|FLASH_FLAG_WRPRTERR);//清除標(biāo)志位

     FLASH_Lock();    //鎖定FLASH編程擦除控制器
}

//FLASH讀出數(shù)據(jù)
u16 FLASH_R(u32 add){ //參數(shù)1:32位讀出FLASH地址。返回值:16位數(shù)據(jù)
	u16 a;
    a = *(u16*)(add);//從指定頁的addr地址開始讀
	return a;
}

main.c

#include "stm32f10x.h" //STM32頭文件
#include "sys.h"
#include "delay.h"
#include "led.h"
#include "key.h" 

#include "flash.h" //導(dǎo)入Flash的頭文件

#define FLASH_START_ADDR  0x0801f000	  //寫入的起始地址

int main (void){//主程序
	u16 a; //定義變量
	//初始化程序
	RCC_Configuration(); //時(shí)鐘設(shè)置
	LED_Init();//LED初始化
	KEY_Init();//按鍵初始化

    a = FLASH_R(FLASH_START_ADDR);//從指定頁的地址讀FLASH
        //b = FLASH_R(FLASH_START_ADDR);多個(gè)情況
	GPIO_Write(LEDPORT,a); //直接數(shù)值操作將變量值寫入LED(LED在GPIOB組的PB0和PB1上)
                           //整組寫入LED(PB組)
        //GPIO_Write(LEDPORT,a,b);多個(gè)情況


	//主循環(huán)
	while(1){

		//示例4:有鎖存
		if(!GPIO_ReadInputDataBit(KEYPORT,KEY1)){ //讀按鍵接口的電平
			delay_ms(20); //延時(shí)20ms去抖動(dòng)
			if(!GPIO_ReadInputDataBit(KEYPORT,KEY1)){ //讀按鍵接口的電平
				//在2個(gè)LED上顯示二進(jìn)制加法
				a++; //變量加1
				if(a>3){ //當(dāng)變量大于3時(shí)清0
					a=0; 
				}
				GPIO_Write(LEDPORT,a); //直接數(shù)值操作將變量值寫入LED(LED在GPIOB組的PB0和PB1上)

				FLASH_W(FLASH_START_ADDR,a); //將led的狀態(tài)值a寫入,指定FLASH起始頁的地址內(nèi)
                //FLASH_W(FLASH_START_ADDR,a,b);多個(gè)情況

				while(!GPIO_ReadInputDataBit(KEYPORT,KEY1)); //等待按鍵松開 
			}
		}
	}
}

flash操作注意事項(xiàng)

操作一定要先擦后寫

每頁是1024個(gè)地址,起始地址Ox08000000

擦除操作以頁為單位,寫操作則必須以16位寬度為單位,允許跨頁寫入

STM32內(nèi)置FLASH擦或?qū)憰r(shí),必須打開外部/內(nèi)部高速振蕩器

FLASH可多次擦寫10萬次,不可死循環(huán)擦寫

擦寫時(shí)要避開用戶程序存儲(chǔ)區(qū)的區(qū)域,否則會(huì)擦掉用戶程序?qū)е洛e(cuò)誤

擦除一頁要10ms(對(duì)于1k大小的一頁),比較慢。而且不能單個(gè)字節(jié)的擦寫

擦除只能以頁擦除:臨時(shí)存儲(chǔ)寫入地址(空白區(qū)域盡量靠后)? ?不能和? ? 下載用戶程序(第0頁開始)相互沖突?

STM32基礎(chǔ)入門學(xué)習(xí)筆記:核心板 電路原理與驅(qū)動(dòng)編程,# STM32,學(xué)習(xí),筆記

三:蜂鳴器驅(qū)動(dòng)程序(按鍵有聲音)

原理:通過延遲時(shí)間決定頻率震動(dòng) 和 高低電平循環(huán)次數(shù)決定持續(xù)時(shí)長 進(jìn)行控制?

核心板蜂鳴器電路

STM32基礎(chǔ)入門學(xué)習(xí)筆記:核心板 電路原理與驅(qū)動(dòng)編程,# STM32,學(xué)習(xí),筆記

STM32基礎(chǔ)入門學(xué)習(xí)筆記:核心板 電路原理與驅(qū)動(dòng)編程,# STM32,學(xué)習(xí),筆記

在Hardware文件夾中——>創(chuàng)建一個(gè)BUZZER文件夾(buzzer.c buzzer.h)

buzzer.h

#ifndef    ——BUZZZER_H
#define    ——BUZZZER_H
#include "sys.h"


#define BUZZERPORT	GPIOB	 //定義IO接口     端口組PB5
#define LED1 GPIO_ Pin_o //定義工o接口
#define LED2 GPIO_ Pin_1 //定義工o接口


#define BUZZER	GPIO_Pin_5	 //定義IO接口     IO端口


void BUZZER_Init(void);   //初始化
void BUZZER_BEEP1(void);  //響一聲


#endif

buzzer.c

#include "buzzer.h"
#include "delay.h"



//蜂鳴器的接口初始化
void BUZZER_Init(void)
    {                                               
    GPIO_InitTypeDef  GPIO_InitStructure; 	
    GPIO_InitStructure.GPIO_Pin = BUZZER;            //選擇端口號(hào)                        
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //選擇IO接口工作方式       
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//設(shè)置IO接口速度(2/10/50MHz)    
    GPIO_Init(BUZZERPORT, &GPIO_InitStructure);	
    
    GPIO_WriteBit(BUZZERPORT,BUZZER,(BitAction)(1)); //蜂鳴器接口輸出高電平1	,斷開線路,保護(hù)蜂鳴器不被損壞或燒壞
    }



//蜂鳴器響一聲t
//延遲時(shí)間長度決定總周期的長度(修改聲音的頻率音調(diào))? ??循環(huán)次數(shù)i決定蜂鳴器發(fā)出(聲音持續(xù)時(shí)間的長度)
void BUZZER_BEEP1(void)                                  //1kHz
    {                                                    //蜂鳴器響一聲
    u16 i;
    for(i=0;i<200;i++)
        {
        GPIO_WriteBit(BUZZERPORT,BUZZER,(BitAction)(0)); //蜂鳴器接口輸出0
            delay_us(500);                               //延時(shí)		
        GPIO_WriteBit(BUZZERPORT,BUZZER,(BitAction)(1)); //蜂鳴器接口輸出高電平1
            delay_us(500);                               //延時(shí)		
        }
    }

main.c

#include "stm32f10x.h" //STM32頭文件
#include "sys.h"
#include "delay.h"
#include "led.h"
#include "key.h"
#include "flash.h" 

#include "buzzer.h" 
#define FLASH_START_ADDR  0x0801f000	  //寫入的起始地址

int main (void){//主程序
	u8 a; //定義變量

	//初始化程序
	RCC_Configuration(); //時(shí)鐘設(shè)置
	LED_Init();//LED初始化
	KEY_Init();//按鍵初始化

	BUZZER_Init();//蜂鳴器初始化
	BUZZER_BEEP1();//蜂鳴器響1khz

	a = FLASH_R(FLASH_START_ADDR);//從指定頁的地址讀FLASH

    //處理PB1 PB2
	//因?yàn)閘ed是PB0和PB1蜂鳴器的接口,同時(shí)是PB5也是。一設(shè)置低電平PB端口就全部為0了(默認(rèn)是PB0 PB1,但這里加入了PB5 就會(huì)使蜂鳴器長時(shí)間導(dǎo)致發(fā)熱)
	    //GPIO_ReadOutputData讀取整組(LED在GPIOB組)的io口的電平狀態(tài)	 按位與優(yōu)先級(jí)高
	    //0xfffc&GPIO_ReadOutputData(LEDPORT))高14位保持io口的原來狀態(tài),低兩位清零
	    //然后與a進(jìn)行與運(yùn)算操作變量a的最低兩位,再寫入PB組的最低兩位,其他PB組的其他位不變:將led狀態(tài)寫入,也就是說led在狀態(tài)寫入的時(shí)候不會(huì)影響其他io電平
    GPIO_Write(LEDPORT,a|0xfffc&GPIO_ReadOutputData(LEDPORT)); //直接數(shù)值操作將變量值寫入LED(LED在GPIOB組的PB0和PB1上)

	//主循環(huán)
	while(1){
		//示例4:有鎖存
		if(!GPIO_ReadInputDataBit(KEYPORT,KEY1)){ //讀按鍵接口的電平
			delay_ms(20); //延時(shí)20ms去抖動(dòng)
			if(!GPIO_ReadInputDataBit(KEYPORT,KEY1)){ //讀按鍵接口的電平
				//在2個(gè)LED上顯示二進(jìn)制加法
				a++; //變量加1
				if(a>3){ //當(dāng)變量大于3時(shí)清0
					a=0; 
				}
				GPIO_Write(LEDPORT,a|0xfffc&GPIO_ReadOutputData(LEDPORT)); //整組寫入不是某個(gè)引腳直接數(shù)值操作將變量值寫入LED(LED在GPIOB組的PB0和PB1上)
				//a=1是001->pa0=1,a=2是010->pa0=0 pa1=1,a=3是011->pa0=1 pa1=1,a=4是100->pa0=0 pa1=0
				BUZZER_BEEP1();//蜂鳴器音1

				FLASH_W(FLASH_START_ADDR,a); //從指定頁的地址寫入FLASH

				while(!GPIO_ReadInputDataBit(KEYPORT,KEY1)); //等待按鍵松開 
                //BUZZER_BEEP2();//蜂鳴器音2
			}
		}
	}
}

四:MIDI音樂播放程序(基于蜂鳴器)

原理:通過改變音調(diào)頻率 和 時(shí)間長度使用蜂鳴器進(jìn)行控制?

音調(diào)與頻率的關(guān)系?

STM32基礎(chǔ)入門學(xué)習(xí)筆記:核心板 電路原理與驅(qū)動(dòng)編程,# STM32,學(xué)習(xí),筆記

buzzer.c

uc16 music1[78]={ //音樂的數(shù)據(jù)表(奇數(shù)是音調(diào)頻率,偶數(shù)是時(shí)間長度),存于flash中
330,750,
440,375,
494,375,
523,750,
587,375,
659,375,
587,750,
494,375,
392,375,
440,1500,
330,750,
440,375,
494,375,
523,750,
587,375,
659,375,
587,750,
494,375,
392,375,
784,1500,
659,750,
698,375,
784,375,
880,750,
784,375,
698,375,
659,750,
587,750,
659,750,
523,375,
494,375,
440,750,
440,375,
494,375,
523,750,
523,750,
494,750,
392,750,
440,3000
};



//MIDI音樂
void MIDI_PLAY(void){     
	u16 i,e;
    39個(gè)音符循環(huán)一次
	for(i=0;i<39;i++){    
        //循環(huán)不同次數(shù)達(dá)到讓同一個(gè)音符播放一段時(shí)間長度
        //music1[i*2]——>0——>330    music1[i*2+1]——>1——>750    (1赫茲=1次/秒)?
        //意思:每秒鐘震動(dòng)330次[Hz],750毫秒[T]震動(dòng)多少次呢[次數(shù)=Hz*T]?
		for(e=0;e<music1[i*2]*music1[i*2+1]/1000;e++){    //轉(zhuǎn)化為毫秒us 也就是xxx/1000
            //方波的時(shí)間,音效音調(diào)高低頻率,高電平的延時(shí)時(shí)間500000us+低電平的延時(shí)時(shí)間500000us=形成1秒頻率周期	
			GPIO_WriteBit(BUZZERPORT,BUZZER,(BitAction)(0)); //蜂鳴器接口輸出0
			    delay_us(500000/music1[i*2]); //延時(shí)    1/Hz=s
			GPIO_WriteBit(BUZZERPORT,BUZZER,(BitAction)(1)); //蜂鳴器接口輸出高電平1
			    delay_us(500000/music1[i*2]); //延時(shí)	
		}	
	}
}

buzzer.h

void MIDI PLAY(void);    //MIDI_PLAY函數(shù)聲明

main.c

BUZZER_Init ();//蜂鳴器初始化
//BUZZER_BEEP1(0)://蜂鳴器響1khz

MIDI_PLAY(); //播放MIDI音樂

五:USART串口通信驅(qū)動(dòng)程序(串口助手 超級(jí)終端)

STM32基礎(chǔ)入門學(xué)習(xí)筆記:核心板 電路原理與驅(qū)動(dòng)編程,# STM32,學(xué)習(xí),筆記

?STM32基礎(chǔ)入門學(xué)習(xí)筆記:核心板 電路原理與驅(qū)動(dòng)編程,# STM32,學(xué)習(xí),筆記

DYS串口助手使用:設(shè)置自己對(duì)應(yīng)的端口號(hào)(自定義)”C0M4“、波特率(自定義)”115200“、發(fā)送模式(自定義)”數(shù)值“、接收模式(自定義)”數(shù)值“
                 最后點(diǎn)擊打開端口(自定義)、之后關(guān)閉端口(自定義)

                 ”數(shù)值“:16進(jìn)制    ”字符“:ASCLL碼    
                 發(fā)送和接收數(shù)據(jù)可以相互轉(zhuǎn)換:ASCLL碼與進(jìn)制對(duì)應(yīng)表

在Lib文件交接加入:stm32f10x_usart.c


串口助手和FlyMcu:如果公用一個(gè)端口,那么就不能同時(shí)使用

新建文件夾

Basic——>usart——>usart.cusart.h

1.USART發(fā)送程序(3種方法)

usart.h

#ifndef __USART_H
#define __USART_H
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include "stdio.h"	
#include "sys.h" 

#define USART_n		USART1  //定義使用printf函數(shù)的串口,其他串口要使用USART_printf專用函數(shù)發(fā)送

#define USART1_REC_LEN  			200  	//定義USART1最大接收字節(jié)數(shù)
#define USART2_REC_LEN  			200  	//定義USART2最大接收字節(jié)數(shù)
#define USART3_REC_LEN  			200  	//定義USART3最大接收字節(jié)數(shù)

//不使用某個(gè)串口時(shí)要禁止此串口,以減少編譯量
#define EN_USART1 			1		//使能(1)/禁止(0)串口1
#define EN_USART2 			0		//使能(1)/禁止(0)串口2
#define EN_USART3 			0		//使能(1)/禁止(0)串口3
	  	
extern u8  USART1_RX_BUF[USART1_REC_LEN]; //接收緩沖,最大USART_REC_LEN個(gè)字節(jié).末字節(jié)為換行符 
extern u8  USART2_RX_BUF[USART2_REC_LEN]; //接收緩沖,最大USART_REC_LEN個(gè)字節(jié).末字節(jié)為換行符
extern u8  USART3_RX_BUF[USART3_REC_LEN]; //接收緩沖,最大USART_REC_LEN個(gè)字節(jié).末字節(jié)為換行符
 
extern u16 USART1_RX_STA;         		//接收狀態(tài)標(biāo)記	
extern u16 USART2_RX_STA;         		//接收狀態(tài)標(biāo)記	
extern u16 USART3_RX_STA;         		//接收狀態(tài)標(biāo)記	

//函數(shù)聲明
void USART1_Init(u32 bound);//串口1初始化并啟動(dòng)
void USART2_Init(u32 bound);//串口2初始化并啟動(dòng)
void USART3_Init(u32 bound);//串口3初始化并啟動(dòng)
void USART1_printf(char* fmt,...); //串口1的專用printf函數(shù)
void USART2_printf(char* fmt,...); //串口2的專用printf函數(shù)
void USART3_printf(char* fmt,...); //串口3的專用printf函數(shù)

#endif

usart.c

#include "sys.h"
#include "usart.h"
	  	 
//使UASRT串口可用printf函數(shù)發(fā)送
//在usart.h文件里可更換使用printf函數(shù)的串口號(hào)	  
#if 1
#pragma import(__use_no_semihosting)             
//標(biāo)準(zhǔn)庫需要的支持函數(shù)                 
struct __FILE {
	int handle; 
}; 
FILE __stdout;       
//定義_sys_exit()以避免使用半主機(jī)模式    
_sys_exit(int x){ 
	x = x; 
} 
//重定義fputc函數(shù) 
int fputc(int ch, FILE *f){      
	while((USART_n->SR&0X40)==0);//循環(huán)發(fā)送,直到發(fā)送完畢   
    USART_n->DR = (u8) ch;      
	return ch;
}
#endif 





/*USART1串口相關(guān)程序*/
#if EN_USART1   //USART1使用與屏蔽選擇
u8 USART1_RX_BUF[USART1_REC_LEN];     //接收緩沖,最大USART_REC_LEN個(gè)字節(jié).
                                      //接收狀態(tài)
                                      //bit15,	接收完成標(biāo)志
                                      //bit14,	接收到0x0d
                                      //bit13~0,	接收到的有效字節(jié)數(shù)目
u16 USART1_RX_STA=0;                  //接收狀態(tài)標(biāo)記	  

/*USART1專用的printf函數(shù)
當(dāng)同時(shí)開啟2個(gè)以上串口時(shí),printf函數(shù)只能用于其中之一,其他串口要自創(chuàng)獨(dú)立的printf函數(shù)
調(diào)用方法:USART1_printf("123"); //向USART2發(fā)送字符123*/
void USART1_printf (char *fmt, ...)
{ 
  char buffer[USART1_REC_LEN+1];  // 數(shù)據(jù)長度
  u8 i = 0;	
  va_list arg_ptr;
  va_start(arg_ptr, fmt);  
  vsnprintf(buffer, USART1_REC_LEN+1, fmt, arg_ptr);
  while ((i < USART1_REC_LEN) && (i < strlen(buffer)))
  {
    USART_SendData(USART1, (u8) buffer[i++]);
    while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET); 
  }
  va_end(arg_ptr);
}




//串口1初始化并啟動(dòng)
void USART1_Init(u32 bound){ 
  //GPIO端口設(shè)置
  GPIO_InitTypeDef GPIO_InitStructure;
  USART_InitTypeDef USART_InitStructure;
  NVIC_InitTypeDef NVIC_InitStructure;	 
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE);	//使能USART1,GPIOA時(shí)鐘

  //USART1_TX   PA.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;	//復(fù)用推挽輸出
  GPIO_Init(GPIOA, &GPIO_InitStructure);  

  //USART1_RX	  PA.10
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空輸入
  GPIO_Init(GPIOA, &GPIO_InitStructure); 

  //Usart1 NVIC 配置
  NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;   //搶占優(yōu)先級(jí)3
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;		//子優(yōu)先級(jí)3
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			//IRQ通道使能
  NVIC_Init(&NVIC_InitStructure);	//根據(jù)指定的參數(shù)初始化VIC寄存器 

  //USART 初始化設(shè)置
  USART_InitStructure.USART_BaudRate = bound;//波特率 一般設(shè)置為9600;
  USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字長為8位數(shù)據(jù)格式
  USART_InitStructure.USART_StopBits = USART_StopBits_1;//一個(gè)停止位
  USART_InitStructure.USART_Parity = USART_Parity_No;//無奇偶校驗(yàn)位
  USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//無硬件數(shù)據(jù)流控制
  USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;	//收發(fā)模式
  USART_Init(USART1, &USART_InitStructure); //初始化串口
  USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//開啟ENABLE/關(guān)閉DISABLE中斷
  USART_Cmd(USART1, ENABLE);                    //使能串口 
}


//串口1的中斷處理程序
void USART1_IRQHandler(void)
{                       //串口1中斷服務(wù)程序(固定的函數(shù)名不能修改)	
  u8 Res;
                        //以下是字符串接收到USART1_RX_BUF[]的程序,(USART1_RX_STA&0x3FFF)是數(shù)據(jù)的長度(不包括回車)
                        //當(dāng)(USART1_RX_STA&0xC000)為真時(shí)表示數(shù)據(jù)接收完成,即超級(jí)終端里按下回車鍵。
                        //在主函數(shù)里寫判斷if(USART1_RX_STA&0xC000),然后讀USART1_RX_BUF[]數(shù)組,讀到0x0d 0x0a即是結(jié)束。
                        //注意在主函數(shù)處理完串口數(shù)據(jù)后,要將USART1_RX_STA清0
  if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
  {                                     //接收中斷(接收到的數(shù)據(jù)必須是0x0d 0x0a結(jié)尾)		
    Res =USART_ReceiveData(USART1);     //(USART1->DR);	//讀取接收到的數(shù)據(jù)
    printf("%c",Res);                   //把收到的數(shù)據(jù)以 a符號(hào)變量 發(fā)送回電腦		
    if((USART1_RX_STA&0x8000)==0)
    {                                   //接收未完成			
      if(USART1_RX_STA&0x4000)
      {                                 //接收到了0x0d				
        if(Res!=0x0a)
        {
          USART1_RX_STA=0;              //接收錯(cuò)誤,重新開始
        }
        else
        {
          USART1_RX_STA|=0x8000;	    //接收完成了 
        }
      }
      else
      {                                 //還沒收到0X0D					
        if(Res==0x0d)USART1_RX_STA|=0x4000;
        else
        {
          USART1_RX_BUF[USART1_RX_STA&0X3FFF]=Res ; //將收到的數(shù)據(jù)放入數(shù)組
          USART1_RX_STA++;	            //數(shù)據(jù)長度計(jì)數(shù)加1
          if(USART1_RX_STA>(USART1_REC_LEN-1))
          {
            USART1_RX_STA=0;            //接收數(shù)據(jù)錯(cuò)誤,重新開始接收	  
          }
        }		 
      }
    }   		 
  } 
} 
#endif	

main.c

#include "stm32f10x.h" //STM32頭文件
#include "sys.h"
#include "delay.h"
#include "usart.h"



int main (void)
{                        //主程序
  u8 a=7,b=8;
                         //初始化程序
  RCC_Configuration();   //時(shí)鐘設(shè)置
  USART1_Init(115200);   //串口初始化(參數(shù)是波特率)發(fā)送和接收波特率必須完全相同

  //主循環(huán)
  while(1)
  {
    /* 發(fā)送方法1    單個(gè) */
    USART_SendData(USART1, 0x55);    //發(fā)送單個(gè)數(shù)值(那個(gè)端口,發(fā)送什么數(shù)據(jù))
    //USART_SendData(USART1, 'U');  
    while(USART_GetFlagStatus(USART1, USART_FLAG_TC)==RESET); //檢查發(fā)送中斷標(biāo)志位

    /* 發(fā)送方法2     多個(gè)*/
    //	printf("STM32F103 ");          //純字符串發(fā)送數(shù)據(jù)到串口
    //	printf("STM32 %d %d ",a,b);    //純字符串和變量發(fā)送數(shù)據(jù)到串口,a符號(hào)變量
        
    /* 發(fā)送方法3     多個(gè)    專用的*/
    //	USART1_printf("STM32 %d %d ",a,b);

    delay_ms(1000);                    //延時(shí)
  }
}

2.USART接收程序(2種方法)

2.1 查詢方式接收數(shù)據(jù)?

查詢要在usart.c的USART初始化設(shè)置中關(guān)閉中斷(當(dāng)串口接收到數(shù)據(jù)時(shí)才不會(huì)跳到中斷函數(shù)中)ENABLE——>DISABLE

main.c
u8 a;

while(){
    //查詢方式接收(發(fā)回去,又接收回來),失去實(shí)時(shí)性
    if(USART_GetFlagStatus(USART1,USART_FLAG_RXNE)!= RESET){    //查詢串口待處理標(biāo)志位    接收數(shù)據(jù)寄存器非空標(biāo)志位
        a =USART_ReceiveData(USART1);                           //讀取接收到的數(shù)據(jù)
        printf ("%c",a);                                        //把收到的數(shù)據(jù)發(fā)送回電腦
    }
}

2.2 中斷方式接收數(shù)據(jù)

?中斷要在usart.c的USART初始化設(shè)置中關(guān)閉中斷(當(dāng)串口接收到數(shù)據(jù)時(shí)才不會(huì)跳到中斷函數(shù)中)DISABLE——>ENABLE

usart.c
//中斷方式接收程序解讀
void USART1_IRQHandler(void){ //串口1中斷服務(wù)程序(固定的函數(shù)名不能修改)	
	u8 a;
	if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET){      //接收中斷(接收到的數(shù)據(jù)必須是0x0d 0x0a結(jié)尾)		
		a=USART_ReceiveData(USART1);                            //(USART1->DR);	//讀取接收到的數(shù)據(jù)
		printf("%c",a);                                         //把收到的數(shù)據(jù)以 a符號(hào)變量 發(fā)送回電腦	
		}

3.USART串口控制程序(雙向交互):通過串口助手控制LED燈的開關(guān)狀態(tài)和蜂鳴器、在單片機(jī)中按鍵操作在串口助手中進(jìn)行顯示

這里需要使用超級(jí)終端:并且可以改變終端輸出的顏色背景?

輸入輸出可以一起顯示


建立連接
    1.文件——>新建連接——>選擇合適的串口(自定義)COM4——>確定
    2.修改
        串口(自定義):COM4
        波特率(自定義):115200
        編碼:GB2312
    3.最后點(diǎn)擊確定


斷開連接
    串口名字上——>右鍵——>關(guān)閉

main.c

#include "stm32f10x.h" //STM32頭文件
#include "sys.h"
#include "delay.h"
#include "led.h"
#include "key.h"
#include "buzzer.h"
#include "usart.h"
int main (void){//主程序
	u8 a;
	//初始化程序
	RCC_Configuration(); //時(shí)鐘設(shè)置
	LED_Init();//LED初始化
	KEY_Init();//按鍵初始化
	BUZZER_Init();//蜂鳴器初始化
	USART1_Init(115200); //串口初始化(參數(shù)是波特率)

	//主循環(huán)
	while(1){

		//采用查詢方式接收   
        //查詢要在usart.c的USART初始化設(shè)置中關(guān)閉中斷(當(dāng)串口接收到數(shù)據(jù)時(shí)才不會(huì)跳到中斷函數(shù)中)ENABLE——>DISABLE 
		if(USART_GetFlagStatus(USART1,USART_FLAG_RXNE) != RESET){  //查詢串口待處理標(biāo)志位
			a =USART_ReceiveData(USART1);//讀取接收到的數(shù)據(jù)
			switch (a){
				case '0':
					GPIO_WriteBit(LEDPORT,LED1,(BitAction)(0)); //LED控制
					printf("%c:LED1 OFF ",a); //不能使用中文
					break;
				case '1':
					GPIO_WriteBit(LEDPORT,LED1,(BitAction)(1)); //LED控制
					printf("%c:LED1 ON ",a); 
					break;
				case '2':
					BUZZER_BEEP1(); //蜂鳴一聲
					printf("%c:BUZZER ",a); //把收到的數(shù)據(jù)發(fā)送回電腦
					break;
				default:
					break;
			}		  
		}

		//按鍵控制
		if(!GPIO_ReadInputDataBit(KEYPORT,KEY1)){ //讀按鍵接口的電平
			delay_ms(20); //延時(shí)20ms去抖動(dòng)
			if(!GPIO_ReadInputDataBit(KEYPORT,KEY1)){ //讀按鍵接口的電平
				while(!GPIO_ReadInputDataBit(KEYPORT,KEY1)); //等待按鍵松開 
				printf("KEY1 "); 
                printf("KEY1 "); 
			}
		}		 
		if(!GPIO_ReadInputDataBit(KEYPORT,KEY2)){ //讀按鍵接口的電平
			delay_ms(20); //延時(shí)20ms去抖動(dòng)
			if(!GPIO_ReadInputDataBit(KEYPORT,KEY2)){ //讀按鍵接口的電平
				while(!GPIO_ReadInputDataBit(KEYPORT,KEY2)); //等待按鍵松開
 
				printf("\O33[1;40;32m KEY2 ");            //改變字體顏色和背景色
                printf("\O33[1;40;32m KEY2 \O33[om");     //改變字體顏色和背景色,之后又改回來
                printf("\O33[1;40;32m KEY2 /n/r");        //改變字體顏色和背景色,再次按顯示到下一行
			}
		}		 

//      delay_ms(1000); //延時(shí)
	}
}

4.超級(jí)終端串口遠(yuǎn)程控制LED程序(命令行操作形式)

usart.h

#define USART1_REC_LEN    200;    //定義USART1最大接收字節(jié)數(shù)
#define USART2_REC_LEN    200;
#define USART3_REC_LEN    200;


//全局變量聲明
extern u8 USART1_RX_BUF[USART1_REC_LEN];    //接收緩存,最大USART_REC_LEN個(gè)字節(jié)末字節(jié)為換行符
extern u8 USART2_RX_BUF[USART2_REC_LEN];    
extern u8 USART3_RX_BUF[USART3_REC_LEN];   


extern u16 USART1_RX_STA;    //接收狀態(tài)標(biāo)記
extern u16 USART2_RX_STA;
extern u16 USART3_RX_STA;

usart.c????????

u8 USART1_RX_BUF[USART1_REC_LEN];    //接收緩沖,最大USART1_REC_LEN個(gè)字節(jié)
//全局變量
u16 USART1_RX_STA=0;    //接收狀態(tài)標(biāo)記



//通過中斷函數(shù)接收數(shù)據(jù)
//中斷要在usart.c的USART初始化設(shè)置中關(guān)閉中斷(當(dāng)串口接收到數(shù)據(jù)時(shí)才不會(huì)跳到中斷函數(shù)中)DISABLE——>ENABLE
void USART1_IRQHandler(void)
{ //串口1中斷服務(wù)程序(固定的函數(shù)名不能修改)	
  u8 Res;
  //以下是字符串接收到USART_RX_BUF[]的程序,(USART_RX_STA&0x3FFF)是數(shù)據(jù)的長度(不包括回車)
  //當(dāng)(USART_RX_STA&0xC000)為真時(shí)表示數(shù)據(jù)接收完成,即超級(jí)終端里按下回車鍵。
  //在主函數(shù)里寫判斷if(USART_RX_STA&0xC000),然后讀USART_RX_BUF[]數(shù)組,讀到0x0d 0x0a即是結(jié)束
  //注意在主函數(shù)處理完串口數(shù)據(jù)后,要將USART_RX_STA清0

//多字符指令接收
  if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) {    //接收中斷(接收到的數(shù)據(jù)必須是0x0d回車符 0x0a結(jié)尾)		
    Res =USART_ReceiveData(USART1);//(USART1->DR);	//讀取接收到的數(shù)據(jù)
    printf("%c",Res); //把收到的數(shù)據(jù)以 a符號(hào)變量 發(fā)送回電腦
	
    //USART1_RX_STA初始值為0	
    if((USART1_RX_STA&0x8000)==0) {    //接收未完成	接收狀態(tài)標(biāo)記	最高位第1位	    定義了初始為0
      if(USART1_RX_STA&0x4000){        //接收到了0x0d		        最高位第2位
        //判斷是不是0x0a /r			
        if(Res!=0x0a)
            {USART1_RX_STA=0;}             //接收錯(cuò)誤,重新開始,狀態(tài)位清零
        else
            {USART1_RX_STA|=0x8000;}       //接收完成了,是0x0a,那么把最高位狀態(tài)位置1【11】
      }else{//還沒收到0X0D     /n按鍵	    回車鍵=ox0D+0x0a組合=/n/r	
        //是回車,第二位置1			
        if(Res==0x0d){USART1_RX_STA|=0x4000;}    //0100 0 0 0     最高位第2位 置1【11】
        //不是回車去除掉最高兩位
        else
        {
          USART1_RX_BUF[USART1_RX_STA&0X3FFF]=Res ; //將收到的數(shù)據(jù)放入數(shù)組    最高位的2位去除掉	    0011FFF

          USART1_RX_STA++;	//數(shù)據(jù)長度計(jì)數(shù)加1
          if(USART1_RX_STA>(USART1_REC_LEN-1))     //讀到的值超過數(shù)組的最大值
              {USART1_RX_STA=0;}                   //接收數(shù)據(jù)錯(cuò)誤,重新開始接收,狀態(tài)標(biāo)志清零	            
        }		 
      }
    }
  }
}

mian.c

#include "stm32f10x.h" //STM32頭文件
#include "sys.h"
#include "delay.h"
#include "led.h"
#include "key.h"
#include "buzzer.h"
#include "usart.h"


int main (void){//主程序
	RCC_Configuration();
	LED_Init();//LED初始化
	KEY_Init();//按鍵初始化
	BUZZER_Init();//蜂鳴器初始化
	USART1_Init(115200); //串口初始化,參數(shù)中寫波特率

	USART1_RX_STA=0xC000; //初始值設(shè)為有回車的狀態(tài),即顯示一次歡迎詞

	while(1){
        //判斷最高位和最高位的第二位 是不是1    1100 0 0 0
		if(USART1_RX_STA&0xC000){ //如果標(biāo)志位是0xC000表示收到數(shù)據(jù)串完成,可以處理。
            //判斷數(shù)據(jù)是0個(gè),從而看是不是按了回車    去掉狀態(tài)變量最高兩位0011FFF(表示沒有輸入任何字符)
			if((USART1_RX_STA&0x3FFF)==0){ //單獨(dú)的回車鍵再顯示一次歡迎詞
				printf("\033[1;47;33m\r\n"); //設(shè)置顏色(參考超級(jí)終端使用)
				printf(" 1y--開LED1燈      1n--關(guān)LED1燈 \r\n");
				printf(" 2y--開LED2燈      2n--關(guān)LED2燈 \r\n");
				printf(" 請(qǐng)輸入控制指令,按回車鍵執(zhí)行! \033[0m\r\n");
			}else if((USART1_RX_STA&0x3FFF)==2 && USART1_RX_BUF[0]=='1' && USART1_RX_BUF[1]=='y'){ //判斷數(shù)據(jù)是不是2個(gè),第一個(gè)數(shù)據(jù)是不是“1”,第二個(gè)是不是“y”
				GPIO_SetBits(LEDPORT,LED1); //LED燈都為高電平(1)
				printf("1y -- LED1燈已經(jīng)點(diǎn)亮!\r\n");
			}else if((USART1_RX_STA&0x3FFF)==2 && USART1_RX_BUF[0]=='1' && USART1_RX_BUF[1]=='n'){
				GPIO_ResetBits(LEDPORT,LED1); LED燈都為低電平(0)
				printf("1n -- LED1燈已經(jīng)熄滅!\r\n");
			}else if((USART1_RX_STA&0x3FFF)==2 && USART1_RX_BUF[0]=='2' && USART1_RX_BUF[1]=='y'){
				GPIO_SetBits(LEDPORT,LED2); //LED燈都為高電平(1)
				printf("2y -- LED2燈已經(jīng)點(diǎn)亮!\r\n");
			}else if((USART1_RX_STA&0x3FFF)==2 && USART1_RX_BUF[0]=='2' && USART1_RX_BUF[1]=='n'){
				GPIO_ResetBits(LEDPORT,LED2); LED燈都為低電平(0)
				printf("2n -- LED2燈已經(jīng)熄滅!\r\n");
			}else{ //如果以上都不是,即是錯(cuò)誤的指令。
				printf("指令錯(cuò)誤!\r\n"); 
			}
			USART1_RX_STA=0; //將串口數(shù)據(jù)標(biāo)志位清0
		}
	}
}

六:RTC實(shí)時(shí)時(shí)鐘原理驅(qū)動(dòng)程序

STM32基礎(chǔ)入門學(xué)習(xí)筆記:核心板 電路原理與驅(qū)動(dòng)編程,# STM32,學(xué)習(xí),筆記

?STM32基礎(chǔ)入門學(xué)習(xí)筆記:核心板 電路原理與驅(qū)動(dòng)編程,# STM32,學(xué)習(xí),筆記

1.基于RTC的LED走時(shí)驅(qū)動(dòng)程序(BKP備用寄存器)?

新建文件夾

Basic——>rtc文件夾——>rtc.c?rtc.h


在Lib文件夾下 添加:stm32f10x_rtc.c

LED1代表秒:奇數(shù)點(diǎn)亮,偶數(shù)熄滅;LED2代表分鐘:奇數(shù)點(diǎn)亮,偶數(shù)熄滅

rtc.h

#ifndef __RTC_H
#define __RTC_H	 
#include "sys.h" 


//全局變量的聲明,在rtc.c文件中定義
//以下2條是使用extern語句聲明全局變量,時(shí)鐘計(jì)算出的年月日時(shí)分秒
//注意:這里不能給變量賦值

extern u16 ryear;
extern u8 rmon,rday,rhour,rmin,rsec,rweek;    //年月日時(shí)分秒


//函數(shù)聲明
u8 RTC_Get(void);                                               //讀出當(dāng)前時(shí)間值
u8 RTC_Set(u16 syear,u8 smon,u8 sday,u8 hour,u8 min,u8 sec);    //寫入當(dāng)前時(shí)間值

void RTC_First_Config(void);                                    //首次啟用RTC的設(shè)置(全部初始化)
void RTC_Config(void);                                          //實(shí)時(shí)時(shí)鐘初始化(部分初始化)

//下面包含在時(shí)間讀寫函數(shù)里面,不需要單獨(dú)調(diào)用
u8 Is_Leap_Year(u16 year);                                      //判斷是否是閏年函數(shù)                    
u8 RTC_Get_Week(u16 year,u8 month,u8 day);                      //按年月日計(jì)算星期幾

#endif

rtc.c

#include "sys.h"
#include "rtc.h"


//以下2條全局變量--用于RTC時(shí)間的讀取
u16 ryear; //4位年
u8 rmon,rday,rhour,rmin,rsec,rweek;//2位月日時(shí)分秒周


//首次啟用RTC的初始化設(shè)置
void RTC_First_Config(void){ 
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);//啟用PWR電源管理部分和BKP備用寄存器的時(shí)鐘(from APB1)
    PWR_BackupAccessCmd(ENABLE);//后備域解鎖    使能或者失能RTC和后備寄存器訪問
    BKP_DeInit();//備份寄存器模塊復(fù)位            將外設(shè)BKP的全部寄存器重設(shè)為缺省值
    RCC_LSEConfig(RCC_LSE_ON);//外部32.768KHZ晶振開啟   
    while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET);//等待穩(wěn)定    
    RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);//RTC時(shí)鐘源配置成LSE(外部低速晶振32.768KHZ)    
    RCC_RTCCLKCmd(ENABLE);//RTC開啟    
    RTC_WaitForSynchro();//開啟后需要等待APB1時(shí)鐘與RTC時(shí)鐘同步,才能讀寫寄存器    
    RTC_WaitForLastTask();//讀寫寄存器前,要確定上一個(gè)操作已經(jīng)結(jié)束
    RTC_SetPrescaler(32767);//設(shè)置RTC分頻器,使RTC時(shí)鐘為1Hz,RTC period = RTCCLK/RTC_PR = (32.768 KHz)/(32767+1)   
    RTC_WaitForLastTask();//等待寄存器寫入完成	
    //當(dāng)不使用RTC秒中斷,可以屏蔽下面2條
//    RTC_ITConfig(RTC_IT_SEC, ENABLE);//使能秒中斷   
//    RTC_WaitForLastTask();//等待寫入完成
}


//實(shí)時(shí)時(shí)鐘一般初始化設(shè)置
void RTC_Config(void){ 
    //在BKP的后備寄存器1中,存了一個(gè)特殊字符0xA5A5
    //第一次上電或后備電源掉電后,該寄存器數(shù)據(jù)丟失,表明RTC數(shù)據(jù)丟失,需要重新配置
    if (BKP_ReadBackupRegister(BKP_DR1) != 0xA5A5){//判斷寄存數(shù)據(jù)是否丟失  從指定的后備寄存器中讀取數(shù)據(jù)       
        RTC_First_Config();//重新配置RTC        
        BKP_WriteBackupRegister(BKP_DR1, 0xA5A5);//配置完成后,向后備寄存器中寫特殊字符0xA5A5
    }else{
		//若后備寄存器沒有掉電,則無需重新配置RTC
        //這里我們可以利用RCC_GetFlagStatus()函數(shù)查看本次復(fù)位類型
        if (RCC_GetFlagStatus(RCC_FLAG_PORRST) != RESET){
            //這是上電復(fù)位
        }
        else if (RCC_GetFlagStatus(RCC_FLAG_PINRST) != RESET){
            //這是外部RST管腳復(fù)位
        }       
        RCC_ClearFlag();//清除RCC中復(fù)位標(biāo)志

        //雖然RTC模塊不需要重新配置,且掉電后依靠后備電池依然運(yùn)行
        //但是每次上電后,還是要使能RTCCLK
        RCC_RTCCLKCmd(ENABLE);//使能RTCCLK        
        RTC_WaitForSynchro();//等待RTC時(shí)鐘與APB1時(shí)鐘同步

        //當(dāng)不使用RTC秒中斷,可以屏蔽下面2條
//        RTC_ITConfig(RTC_IT_SEC, ENABLE);//使能秒中斷        
//        RTC_WaitForLastTask();//等待操作完成
    }
    //是否啟用rtc的輸出功能,一般情況下不使用
	#ifdef RTCClockOutput_Enable   
	    RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);
	    PWR_BackupAccessCmd(ENABLE);   
	    BKP_TamperPinCmd(DISABLE);   
	    BKP_RTCOutputConfig(BKP_RTCOutputSource_CalibClock);
	#endif
}



//RTC時(shí)鐘1秒觸發(fā)中斷函數(shù)(名稱固定不可修改)
void RTC_IRQHandler(void){
	if (RTC_GetITStatus(RTC_IT_SEC) != RESET){
        //寫入自己的程序
	}
	RTC_ClearITPendingBit(RTC_IT_SEC); 
	RTC_WaitForLastTask();
}

//鬧鐘中斷處理(啟用時(shí)必須調(diào)高其優(yōu)先級(jí))
void RTCAlarm_IRQHandler(void){
	if(RTC_GetITStatus(RTC_IT_ALR) != RESET){
	
	}
	RTC_ClearITPendingBit(RTC_IT_ALR);
	RTC_WaitForLastTask();
}



//時(shí)間讀寫計(jì)算
//判斷是否是閏年函數(shù)
//月份   1  2  3  4  5  6  7  8  9  10 11 12
//閏年   31 29 31 30 31 30 31 31 30 31 30 31
//非閏年 31 28 31 30 31 30 31 31 30 31 30 31
//輸入:年份
//輸出:該年份是不是閏年.1,是.0,不是
u8 Is_Leap_Year(u16 year){                    
	if(year%4==0){ //必須能被4整除
		if(year%100==0){		
			if(year%400==0)return 1;//如果以00結(jié)尾,還要能被400整除          
			else return 0;  
		}else return 1;  
	}else return 0;
}                           
//設(shè)置時(shí)鐘
//把輸入的時(shí)鐘轉(zhuǎn)換為秒鐘
//以1970年1月1日為基準(zhǔn)
//1970~2099年為合法年份

//月份數(shù)據(jù)表                                                                       
u8 const table_week[12]={0,3,3,6,1,4,6,2,5,0,3,5}; //月修正數(shù)據(jù)表  
const u8 mon_table[12]={31,28,31,30,31,30,31,31,30,31,30,31};//平年的月份日期表

//寫入時(shí)間
u8 RTC_Set(u16 syear,u8 smon,u8 sday,u8 hour,u8 min,u8 sec){ //寫入當(dāng)前時(shí)間(1970~2099年有效),
	u16 t;
	u32 seccount=0;
	if(syear<2000||syear>2099)return 1;//syear范圍1970-2099,此處設(shè)置范圍為2000-2099       
	for(t=1970;t<syear;t++){ //把所有年份的秒鐘相加
		if(Is_Leap_Year(t))seccount+=31622400;//閏年的秒鐘數(shù)
		else seccount+=31536000;                    //平年的秒鐘數(shù)
	}
	smon-=1;
	for(t=0;t<smon;t++){         //把前面月份的秒鐘數(shù)相加
		seccount+=(u32)mon_table[t]*86400;//月份秒鐘數(shù)相加
		if(Is_Leap_Year(syear)&&t==1)seccount+=86400;//閏年2月份增加一天的秒鐘數(shù)        
	}
	seccount+=(u32)(sday-1)*86400;//把前面日期的秒鐘數(shù)相加
	seccount+=(u32)hour*3600;//小時(shí)秒鐘數(shù)
	seccount+=(u32)min*60;      //分鐘秒鐘數(shù)
	seccount+=sec;//最后的秒鐘加上去
	RTC_First_Config(); //重新初始化時(shí)鐘
	BKP_WriteBackupRegister(BKP_DR1, 0xA5A5);//配置完成后,向后備寄存器中寫特殊字符0xA5A5
	RTC_SetCounter(seccount);//把換算好的計(jì)數(shù)器值寫入
	RTC_WaitForLastTask(); //等待寫入完成
	return 0; //返回值:0,成功;其他:錯(cuò)誤代碼.    
}

//讀出時(shí)間
u8 RTC_Get(void){//讀出當(dāng)前時(shí)間值 //返回值:0,成功;其他:錯(cuò)誤代碼.
	static u16 daycnt=0;
	u32 timecount=0;
	u32 temp=0;
	u16 temp1=0;
	timecount=RTC_GetCounter();		
	temp=timecount/86400;   //得到天數(shù)(秒鐘數(shù)對(duì)應(yīng)的)
	if(daycnt!=temp){//超過一天了
		daycnt=temp;
		temp1=1970;  //從1970年開始
		while(temp>=365){
		     if(Is_Leap_Year(temp1)){//是閏年
			     if(temp>=366)temp-=366;//閏年的秒鐘數(shù)
			     else {temp1++;break;} 
		     }
		     else temp-=365;       //平年
		     temp1++; 
		}  
		ryear=temp1;//得到年份
		temp1=0;
		while(temp>=28){//超過了一個(gè)月
			if(Is_Leap_Year(ryear)&&temp1==1){//當(dāng)年是不是閏年/2月份
				if(temp>=29)temp-=29;//閏年的秒鐘數(shù)
				else break;
			}else{
	            if(temp>=mon_table[temp1])temp-=mon_table[temp1];//平年
	            else break;
			}
			temp1++; 
		}
		rmon=temp1+1;//得到月份
		rday=temp+1;  //得到日期
	}
	temp=timecount%86400;     //得到秒鐘數(shù)      
	rhour=temp/3600;     //小時(shí)
	rmin=(temp%3600)/60; //分鐘     
	rsec=(temp%3600)%60; //秒鐘
	rweek=RTC_Get_Week(ryear,rmon,rday);//獲取星期  
	return 0;
}    


//獲取星期幾
//按年月日計(jì)算星期(只允許1901-2099年)//已由RTC_Get調(diào)用    
u8 RTC_Get_Week(u16 year,u8 month,u8 day){ 
	u16 temp2;
	u8 yearH,yearL;
	yearH=year/100;     
	yearL=year%100;
	// 如果為21世紀(jì),年份數(shù)加100 
	if (yearH>19)yearL+=100;
	// 所過閏年數(shù)只算1900年之后的 
	temp2=yearL+yearL/4;
	temp2=temp2%7;
	temp2=temp2+day+table_week[month-1];
	if (yearL%4==0&&month<3)temp2--;
	return(temp2%7); //返回星期值
}

main.c

#include "stm32f10x.h" //STM32頭文件
#include "sys.h"
#include "delay.h"
#include "led.h"
#include "key.h"
#include "buzzer.h"
#include "usart.h"

#include "rtc.h"


int main (void){//主程序
	RCC_Configuration(); //系統(tǒng)時(shí)鐘初始化

	RTC_Config(); //實(shí)時(shí)時(shí)鐘初始化
 
	LED_Init();//LED初始化
	KEY_Init();//按鍵初始化
	BUZZER_Init();//蜂鳴器初始化
	USART1_Init(115200); //串口初始化,參數(shù)中寫波特率
	USART1_RX_STA=0xC000; //初始值設(shè)為有回車的狀態(tài),即顯示一次歡迎詞
	while(1){
		if(RTC_Get()==0){ //讀出時(shí)間值,同時(shí)判斷返回值是不是0,非0時(shí)讀取的值是錯(cuò)誤的。	
			GPIO_WriteBit(LEDPORT,LED1,(BitAction)(rsec%2)); //LED1接口    讀出秒數(shù),取余表示led的狀態(tài)    
			GPIO_WriteBit(LEDPORT,LED2,(BitAction)(rmin%2)); //LED2接口    讀出分鐘數(shù),取余表示led的狀態(tài)    
		}
	}
}

2.RTC超級(jí)終端串口顯示日歷程序(命令行操作形式)

在超級(jí)終端按回車鍵,之后顯示更新時(shí)間?初始化時(shí)鐘 輸入設(shè)置時(shí)間

usart.c

//開啟中斷
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//開啟ENABLE/關(guān)閉DISABLE中斷

main.c

#include "stm32f10x.h"    //STM32頭文件
#include "sys.h"
#include "delay.h"
#include "led.h"
#include "key.h"
#include "buzzer.h"
#include "usart.h"
#include "rtc.h"




int main (void){//主程序
  u8 bya;
  RCC_Configuration(); //系統(tǒng)時(shí)鐘初始化
  RTC_Config(); //實(shí)時(shí)時(shí)鐘初始化
  LED_Init();//LED初始化
  KEY_Init();//按鍵初始化
  BUZZER_Init();//蜂鳴器初始化
  USART1_Init(115200); //串口初始化,參數(shù)中寫波特率
  USART1_RX_STA=0xC000; //初始值設(shè)為有回車的狀態(tài),即顯示一次歡迎詞


  while(1)
  {
    if(USART1_RX_STA&0xC000)
    { //如果標(biāo)志位是0xC000表示收到數(shù)據(jù)串完成,可以處理。
      if((USART1_RX_STA&0x3FFF)==0)
      { //單獨(dú)的回車鍵再顯示一次歡迎詞
        if(RTC_Get()==0)
        { //讀出時(shí)間值,同時(shí)判斷返回值是不是0,非0時(shí)讀取的值是錯(cuò)誤的。
          printf(" 洋桃開發(fā)板STM32實(shí)時(shí)時(shí)鐘測(cè)試程序   \r\n");
          printf(" 現(xiàn)在實(shí)時(shí)時(shí)間:%d-%d-%d %d:%d:%d  ",ryear,rmon,rday,rhour,rmin,rsec);//顯示日期時(shí)間
          //分鐘和秒鐘的各位與十位分開:單獨(dú)顯示  
          printf(" 現(xiàn)在實(shí)時(shí)時(shí)間:%d-%d-%d %d:%d%d:%d%d  ",ryear,rmon,rday,rhour,rmin/10,rmin%10,rsec/10,rsec%10);//顯示日期時(shí)間          

          if(rweek==0)printf("星期日   \r\n");//rweek值為0時(shí)表示星期日
          if(rweek==1)printf("星期一   \r\n");
          if(rweek==2)printf("星期二   \r\n");
          if(rweek==3)printf("星期三   \r\n");
          if(rweek==4)printf("星期四   \r\n");
          if(rweek==5)printf("星期五   \r\n");
          if(rweek==6)printf("星期六   \r\n");
          printf(" 單按回車鍵更新時(shí)間。輸入字母C初始化時(shí)鐘 \r\n");
          printf(" 請(qǐng)輸入設(shè)置時(shí)間,格式20170806120000,按回車鍵確定! \r\n");
        }
        else
        {
          printf("讀取失??!\r\n");
        }
      }
      else if((USART1_RX_STA&0x3FFF)==1)
      { //判斷數(shù)據(jù)是不是2個(gè)
        if(USART1_RX_BUF[0]=='c' || USART1_RX_BUF[0]=='C')
        {
          RTC_First_Config(); //鍵盤輸入c或C,初始化時(shí)鐘
          BKP_WriteBackupRegister(BKP_DR1, 0xA5A5);//配置完成后,向后備寄存器中寫特殊字符0xA5A5
          printf("初始化成功!      \r\n");//顯示初始化成功
        }
        else
        {
          printf("指令錯(cuò)誤!          \r\n"); //顯示指令錯(cuò)誤!
        } 
      }
      else if((USART1_RX_STA&0x3FFF)==14)
      { //判斷數(shù)據(jù)是不是14個(gè)
        //將超級(jí)終端發(fā)過來的數(shù)據(jù)換算并寫入RTC    ox30是偏移量=0(實(shí)現(xiàn)1~9的對(duì)應(yīng))    
        ryear = (USART1_RX_BUF[0]-0x30)*1000+(USART1_RX_BUF[1]-0x30)*100+(USART1_RX_BUF[2]-0x30)*10+USART1_RX_BUF[3]-0x30;
        rmon = (USART1_RX_BUF[4]-0x30)*10+USART1_RX_BUF[5]-0x30;//串口發(fā)來的是字符,減0x30后才能得到十進(jìn)制0~9的數(shù)據(jù)
        rday = (USART1_RX_BUF[6]-0x30)*10+USART1_RX_BUF[7]-0x30;
        rhour = (USART1_RX_BUF[8]-0x30)*10+USART1_RX_BUF[9]-0x30;
        rmin = (USART1_RX_BUF[10]-0x30)*10+USART1_RX_BUF[11]-0x30;
        rsec = (USART1_RX_BUF[12]-0x30)*10+USART1_RX_BUF[13]-0x30;
        bya=RTC_Set(ryear,rmon,rday,rhour,rmin,rsec); //將數(shù)據(jù)寫入RTC計(jì)算器的程序
        if(bya==0)printf("寫入成功!      \r\n");//顯示寫入成功 
        else printf("寫入失?。?      \r\n"); //顯示寫入失敗
      }
      else
      { //如果以上都不是,即是錯(cuò)誤的指令。
        printf("指令錯(cuò)誤!          \r\n"); //如果不是以上正確的操作,顯示指令錯(cuò)誤!
      }
      USART1_RX_STA=0; //將串口數(shù)據(jù)標(biāo)志位清0
    }
  }
}

七:RCC時(shí)鐘復(fù)位和設(shè)置程序

STM32基礎(chǔ)入門學(xué)習(xí)筆記:核心板 電路原理與驅(qū)動(dòng)編程,# STM32,學(xué)習(xí),筆記

左邊——產(chǎn)生阻頻;左邊——分配阻頻文章來源地址http://www.zghlxwxcb.cn/news/detail-636003.html

rtc.c

//RCC時(shí)鐘的設(shè)置  
void RCC_Configuration(void)
  { 
    ErrorStatus HSEStartUpStatus;       //枚舉定義
    RCC_DeInit();              /* RCC system reset(for debug purpose) RCC寄存器恢復(fù)初始化值*/   
    RCC_HSEConfig(RCC_HSE_ON); /* Enable HSE 使能外部高速晶振*/   
    HSEStartUpStatus = RCC_WaitForHSEStartUp(); /* Wait till HSE is ready 等待外部高速晶振使能完成*/   
    if(HSEStartUpStatus == SUCCESS)
    {   
      /*設(shè)置PLL時(shí)鐘源及倍頻系數(shù)    那種時(shí)鐘源那種方式輸入 倍頻系數(shù)*/   
      RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9); //RCC_PLLMul_x(枚舉2~16)是倍頻值。當(dāng)HSE=8MHZ,RCC_PLLMul_9時(shí)PLLCLK=72MHZ   
      /*設(shè)置AHB時(shí)鐘(HCLK)*/   
      RCC_HCLKConfig(RCC_SYSCLK_Div1); //RCC_SYSCLK_Div1——AHB時(shí)鐘 = 系統(tǒng)時(shí)鐘(SYSCLK) = 72MHZ(外部晶振8HMZ)   
      /*注意此處的設(shè)置,如果使用SYSTICK做延時(shí)程序,此時(shí)SYSTICK(Cortex System timer)=HCLK/8=9MHZ*/   
      RCC_PCLK1Config(RCC_HCLK_Div2); //設(shè)置低速AHB時(shí)鐘(PCLK1),RCC_HCLK_Div2——APB1時(shí)鐘 = HCLK/2 = 36MHZ(外部晶振8HMZ)   
      RCC_PCLK2Config(RCC_HCLK_Div1); //設(shè)置高速AHB時(shí)鐘(PCLK2),RCC_HCLK_Div1——APB2時(shí)鐘 = HCLK = 72MHZ(外部晶振8HMZ)   
      /*注:AHB主要負(fù)責(zé)外部存儲(chǔ)器時(shí)鐘。APB2負(fù)責(zé)AD,I/O,高級(jí)TIM,串口1。APB1負(fù)責(zé)DA,USB,SPI,I2C,CAN,串口2,3,4,5,普通TIM */  
      FLASH_SetLatency(FLASH_Latency_2); //設(shè)置FLASH存儲(chǔ)器延時(shí)時(shí)鐘周期數(shù)   
      /*FLASH時(shí)序延遲幾個(gè)周期,等待總線同步操作。   
      推薦按照單片機(jī)系統(tǒng)運(yùn)行頻率:
      0—24MHz時(shí),取Latency_0;   
      24—48MHz時(shí),取Latency_1;   
      48~72MHz時(shí),取Latency_2*/   
      FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable); //選擇FLASH預(yù)取指緩存的模式,預(yù)取指緩存使能   
      RCC_PLLCmd(ENABLE);	//使能PLL
      while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET); //等待PLL輸出穩(wěn)定   
      RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK); //選擇SYSCLK時(shí)鐘源為PLL
      while(RCC_GetSYSCLKSource() != 0x08); //等待PLL成為SYSCLK時(shí)鐘源   
    }  
    //開啟需要使用的外設(shè)時(shí)鐘
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA |  RCC_APB2Periph_GPIOB 
                          |RCC_APB2Periph_GPIOC| RCC_APB2Periph_GPIOD | RCC_APB2Periph_GPIOE, ENABLE); //APB2外設(shè)時(shí)鐘使能      
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE); //APB1外設(shè)時(shí)鐘使能  
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);   
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);   	 
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);  
  }

mian.c

RCC_Configuration(); //系統(tǒng)時(shí)鐘初始化

led.c

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOC,ENABLE);      //高速總線apb2上啟動(dòng)gpio a/b/c  

到了這里,關(guān)于STM32基礎(chǔ)入門學(xué)習(xí)筆記:核心板 電路原理與驅(qū)動(dòng)編程的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • STM32基于CubeIDE和HAL庫 基礎(chǔ)入門學(xué)習(xí)筆記:物聯(lián)網(wǎng)項(xiàng)目開發(fā)流程和思路

    STM32基于CubeIDE和HAL庫 基礎(chǔ)入門學(xué)習(xí)筆記:物聯(lián)網(wǎng)項(xiàng)目開發(fā)流程和思路

    文章目錄: 第一部分:項(xiàng)目開始前的計(jì)劃與準(zhǔn)備 1.項(xiàng)目策劃和開發(fā)規(guī)范? 1.1 項(xiàng)目要求文檔 1.2 技術(shù)實(shí)現(xiàn)文檔 1.3 開發(fā)規(guī)范 2.創(chuàng)建項(xiàng)目工程與日志 第二部分:調(diào)通硬件電路與驅(qū)動(dòng)程序 第三部分:編寫最基礎(chǔ)的應(yīng)用程序 第四部分:完成最終要求、反復(fù)調(diào)試 第五部分:程序優(yōu)化、

    2024年02月13日
    瀏覽(17)
  • STM32初學(xué)入門筆記(5):使用STM32CubeMX通過SPI,IIC驅(qū)動(dòng)OLED屏幕

    STM32初學(xué)入門筆記(5):使用STM32CubeMX通過SPI,IIC驅(qū)動(dòng)OLED屏幕

    隨著時(shí)代的進(jìn)步,OLED顯示屏成為了繼LCD顯示屏之后的新一代顯示屏技術(shù),OLED具有可視角高,功耗低,厚度薄,耐沖擊、振動(dòng)能力強(qiáng),像素響應(yīng)時(shí)間低等優(yōu)點(diǎn),在嵌入式開發(fā)中,OLED顯示器也是一個(gè)主要的部分,制作OLED顯示模塊的驅(qū)動(dòng)也是學(xué)習(xí)STM32路上的重要一部分,本篇將從

    2024年02月04日
    瀏覽(28)
  • stm32HAL庫學(xué)習(xí)筆記----pwm驅(qū)動(dòng)舵機(jī)

    stm32HAL庫學(xué)習(xí)筆記----pwm驅(qū)動(dòng)舵機(jī)

    目錄 一、目標(biāo) 二、準(zhǔn)備 三、原理 四、cubemx 五、程序 實(shí)現(xiàn)stm32驅(qū)動(dòng)舵機(jī)旋轉(zhuǎn)0°,45°,90°,135°,180°等角度。 stm32f103(c8t6),舵機(jī)(SG90 9g),杜邦線 接線:舵機(jī)紅線-----------5V(mcu) ???????????舵機(jī)棕線-----------GND(mcu) ???????????舵機(jī)黃線-----------PA1(視情況而定

    2023年04月26日
    瀏覽(31)
  • STM32的一鍵下載CH340 DTR RTS與復(fù)位電路NRST的學(xué)習(xí)筆記

    STM32的一鍵下載CH340 DTR RTS與復(fù)位電路NRST的學(xué)習(xí)筆記

    這兩天在學(xué)習(xí)stm32最小系統(tǒng)板的時(shí)候 對(duì)這一部分特別的不理解 于是就去找了很多東西去看? 先說一鍵下載電路吧 先引用一張正點(diǎn)原子的原理圖: 在芯片手冊(cè)上查找ch340的手冊(cè),上面對(duì)于?RTS與DTR的定義是這樣的?: ? 這就說明 我們是可以去控制RTS與DTR的一個(gè)高低電平的 從而

    2023年04月23日
    瀏覽(28)
  • 10、江科大stm32視頻學(xué)習(xí)筆記——PWM驅(qū)動(dòng)led呼吸燈、驅(qū)動(dòng)舵機(jī)、驅(qū)動(dòng)直流機(jī)

    10、江科大stm32視頻學(xué)習(xí)筆記——PWM驅(qū)動(dòng)led呼吸燈、驅(qū)動(dòng)舵機(jī)、驅(qū)動(dòng)直流機(jī)

    目錄 一、PWM驅(qū)動(dòng)LED呼吸燈(燈接在PA0) 1、PWM波和GPIO的對(duì)應(yīng)關(guān)系參考引腳定義表 2、計(jì)數(shù)器的計(jì)算 3、TIM輸出PWM波使用步驟?編輯 4、代碼 (1)輸出化比較單元 (2) PWM.c (3)main.c 5、重映射更換成PA15亮燈 二、PWM驅(qū)動(dòng)舵機(jī)(舵機(jī)接在PA1、按鍵在PB1)? 1、電路圖 2、參數(shù)計(jì)算

    2024年02月14日
    瀏覽(24)
  • 【正點(diǎn)原子STM32】RS485串行通信標(biāo)準(zhǔn)(串口基礎(chǔ)協(xié)議 和 MODBUS協(xié)議、總線連接、通信電路、通信波形圖、RS485相關(guān)HAL庫驅(qū)動(dòng)、RS485配置步驟、)

    【正點(diǎn)原子STM32】RS485串行通信標(biāo)準(zhǔn)(串口基礎(chǔ)協(xié)議 和 MODBUS協(xié)議、總線連接、通信電路、通信波形圖、RS485相關(guān)HAL庫驅(qū)動(dòng)、RS485配置步驟、)

    一、RS485介紹 二、RS485相關(guān)HAL庫驅(qū)動(dòng)介紹 三、RS485配置步驟 四、編程實(shí)戰(zhàn) 五、總結(jié) 串口、UART、TTL、RS232、RS422和RS485之間的關(guān)系可以如此理解: 串口 :是一個(gè)廣義術(shù)語,通常指的是采用串行通信協(xié)議的接口,它可以包括多種具體的物理接口標(biāo)準(zhǔn)和邏輯電平標(biāo)準(zhǔn)。 UART (通用

    2024年04月13日
    瀏覽(30)
  • 小白入門STM32(2)---控制SG90舵機(jī)---基礎(chǔ)工作原理詳解

    小白入門STM32(2)---控制SG90舵機(jī)---基礎(chǔ)工作原理詳解

    本人一枚軟件編程人員,有一定C語言基礎(chǔ),目前自學(xué)STM32單片機(jī),寫下此篇一鞏固所學(xué)二交流分享。 按照慣例,先介紹理論再實(shí)戰(zhàn)上手,穿插習(xí)題,最后給出我的愚見。 SG90屬于一種舵機(jī),最適合小白入門,可直接由單片機(jī)驅(qū)動(dòng)。另外,單片機(jī)中給我們封裝了很多東西,所以

    2023年04月10日
    瀏覽(20)
  • STM32CubeIDE學(xué)習(xí)筆記——使用HAL庫PWM輸出驅(qū)動(dòng)舵機(jī)

    STM32CubeIDE學(xué)習(xí)筆記——使用HAL庫PWM輸出驅(qū)動(dòng)舵機(jī)

    目錄 PWM驅(qū)動(dòng)簡介 工程配置 代碼編寫 這里我采用的是STM32F103C8T6最小系統(tǒng)板,SG-90舵機(jī)實(shí)現(xiàn)功能。 舵機(jī)驅(qū)動(dòng)角度和PWM占空比有關(guān)系,具體對(duì)應(yīng)為50--0度? 150--90度? 250--180度,通過STM32的定時(shí)器功能輸出PWM波來控制舵機(jī)進(jìn)行轉(zhuǎn)動(dòng)。 ?時(shí)鐘選擇外部高速時(shí)鐘 系統(tǒng)映射配置 時(shí)鐘樹設(shè)

    2024年02月13日
    瀏覽(19)
  • STM32之CubeMX學(xué)習(xí)筆記(7)SPI驅(qū)動(dòng)OLED及其優(yōu)化

    STM32之CubeMX學(xué)習(xí)筆記(7)SPI驅(qū)動(dòng)OLED及其優(yōu)化

    購買了邏輯分析儀后,總想著把所有的通訊信號(hào)全都看一遍。之前一篇筆記講的是串口通信,做了一些小實(shí)驗(yàn),搞清楚了如何基于底層利用串口傳一些“非標(biāo)”的數(shù)據(jù)。關(guān)于通信協(xié)議的第二篇,我想來看看SPI通信。 SPI通信是Serial peripheral interface的縮寫,中文是串行外設(shè)接口,

    2024年02月04日
    瀏覽(20)
  • STM32進(jìn)階:使用STM32驅(qū)動(dòng)ST7735S(內(nèi)附核心源碼)

    感覺很久很久沒有來博客更新了,歷經(jīng)千難萬阻,終于做出來了TFT顯示屏的SPI驅(qū)動(dòng),這里分享以下核心源碼,接下來一段時(shí)間開始準(zhǔn)備考科一了,后面有時(shí)間了再來更新,有三種模式下的驅(qū)動(dòng)。 實(shí)驗(yàn)環(huán)境:正點(diǎn)原子 STM32F103ZET6 小型系統(tǒng)板 實(shí)驗(yàn)工具:STM32F103ZET6 芯片與 ST7735S芯

    2024年02月01日
    瀏覽(25)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包