因?yàn)轫?xiàng)目需要,學(xué)習(xí)了一下stm32的GPIO,串口,PWM,中斷部分,在這里做個(gè)小結(jié), 共同學(xué)習(xí),所有程序均經(jīng)過實(shí)際測試,輸出正確。
將GPIO,串口,PWM(定時(shí)器)的配置程序粘貼如下
1、使能外設(shè)的時(shí)鐘:APB1ENR,APB2ENR
2、配置寄存器或者說是控制寄存器。在配置stm32外設(shè)時(shí),任何時(shí)候都要先使能該外設(shè)的時(shí)鐘!而每個(gè)控制寄存器,很有可能包括了,1模式寄存器,2使能寄存器,3才可能是我們認(rèn)為的數(shù)據(jù)寄存器或者內(nèi)容寄存器。
3、使能外設(shè)。即使配置好了,沒有使能外設(shè),則外設(shè)永遠(yuǎn)不會(huì)工作,這一點(diǎn)比較容易遺忘。
寄存器配置,請查看
http://wenku.baidu.com/link?url=NE4LMJFepztwPxYEb0n72SMNZLTruz32JsEJNPAtcV9AcS9OpA6CoLrJGllXzW5relKtY2c8MBKWURnBdYZG_sNj7yg_JFo7cpdut4k1mzS
由于stm32的很多引腳都是復(fù)用,所以在配置寄存器配置時(shí),必須設(shè)置為復(fù)用,復(fù)用切記是默認(rèn)的復(fù)用功能為主,參考文檔,請查看
http://download.csdn.net/detail/bolvtin/8867933
1、外設(shè)時(shí)鐘寄存器
RCC_APB1ENR(APB1外設(shè)時(shí)鐘使能寄存器)
RCC_APB2ENR(APB2外設(shè)時(shí)鐘使能寄存器)
RCC_APB2RSTR(APB2外設(shè)復(fù)位寄存器)
RCC_APB1RSTR(APB1外設(shè)復(fù)位寄存器)
外設(shè)使能寄存器與外設(shè)復(fù)位寄存器存在著對應(yīng)關(guān)系,相應(yīng)位置對應(yīng)相應(yīng)外設(shè)的時(shí)鐘使能與復(fù)位。
注意以下幾個(gè)外設(shè)
1,GPIO--GPIOA,GPIOB,GPIOC,GPIOD,GPIOE,GPIOF,GPIOG時(shí)鐘都在RCC_APB2ENR寄存器
2,串口--USART1時(shí)鐘都在RCC_APB2ENR寄存器
3,定時(shí)器—TIM1,TIM8時(shí)鐘都在RCC_APB2ENR寄存器
1,串口—USART2,USART3,USART4,USART5時(shí)鐘都在RCC_APB1ENR寄存器
2,定時(shí)器—TIM2,TIM3,TIM4,TIM5,TIM6,TIM7時(shí)鐘都在RCC_APB1ENR寄存器,TIM2- TIM5可以產(chǎn)生PWM
注意一下定時(shí)器的內(nèi)部時(shí)鐘信號來源
當(dāng)APB1的時(shí)鐘分頻數(shù)設(shè)置為1,通用定時(shí)器的時(shí)鐘就是APB1的時(shí)鐘;當(dāng)APB1的時(shí)鐘分頻數(shù)設(shè)置為2,通用定時(shí)器TIMx的時(shí)鐘是APB1的2倍,即72Mhz。高級定時(shí)器1,8的時(shí)鐘來自于APB2,不是APB1。
程序部分:
led.h
#ifndef __LED_H
#define __LED_H
#include "sys.h"
//Mini STM32開發(fā)板
//LED驅(qū)動(dòng)代碼
//正點(diǎn)原子@ALIENTEK
//2010/5/27
//LED端口定義
#define LED0 PAout(8)// PA8
#define LED1 PDout(2)// PD2
void LED_Init(void);//初始化
#endif
led.c
#include
#include "led.h"
//////////////////////////////////////////////////////////////////////////////////
//本程序只供學(xué)習(xí)使用,未經(jīng)作者許可,不得用于其它任何用途
//Mini STM32開發(fā)板
//LED驅(qū)動(dòng)代碼
//正點(diǎn)原子@ALIENTEK
//技術(shù)論壇:www.openedv.com
//修改日期:2010/5/27
//版本:V1.0
//版權(quán)所有,盜版必究。
//Copyright(C) 正點(diǎn)原子 2009-2019
//All rights reserved
//////////////////////////////////////////////////////////////////////////////////
//初始化PA8和PD2為輸出口.并使能這兩個(gè)口的時(shí)鐘
//LED IO初始化
/********************************************************************************/
void LED_Init(void)
{
//總體是3部分
//1、使能GPIO的時(shí)鐘,這里假設(shè)使能了A、B、C、D4個(gè)GPIO外設(shè)
//2、配置寄存器,是輸入還是輸出,是默認(rèn)的定義,還是默認(rèn)的復(fù)用功能
//3、填寫默認(rèn)的數(shù)據(jù)參數(shù),這里選擇了,默認(rèn)輸出高電平
RCC->APB2ENR|=1<<2; //使能PORTA時(shí)鐘
RCC->APB2ENR|=1<<3; //使能PORTB時(shí)鐘
RCC->APB2ENR|=1<<4; //使能PORTC時(shí)鐘
RCC->APB2ENR|=1<<5; //使能PORTD時(shí)鐘
GPIOA->CRH&=0XFFFFFFF0; //清掉PA8位原來的設(shè)置,同時(shí)不影響其他位的設(shè)置 在mini stm32上 PA8連接了DS0燈
GPIOA->CRH|=0X00000003;//PA8 推挽輸出
GPIOA->ODR|=1<<8; //PA8 輸出高
GPIOC->CRH&=0XFFF00FFF;
GPIOA->CRH|=0X00038000;//PC11 輸入 PC12 輸出
GPIOA->ODR=1<<11; //PC11 上拉
GPIOA->ODR|=1<<12; //PC.12 輸出高
GPIOD->CRL&=0XFFFFF0FF; //在mini stm32上 PD2連接了DS1燈
GPIOD->CRL|=0X00000300;//PD.2推挽輸出
GPIOD->ODR|=1<<2; //PD.2輸出高
}
timer.h
#ifndef __TIMER_H
#define __TIMER_H
#include "sys.h"
//////////////////////////////////////////////////////////////////////////////////
//本程序只供學(xué)習(xí)使用,未經(jīng)作者許可,不得用于其它任何用途
//Mini STM32開發(fā)板
//通用定時(shí)器 驅(qū)動(dòng)代碼
//正點(diǎn)原子@ALIENTEK
//技術(shù)論壇:www.openedv.com
//修改日期:2010/12/03
//版本:V1.0
//版權(quán)所有,盜版必究。
//Copyright(C) 正點(diǎn)原子 2009-2019
//All rights reserved
//////////////////////////////////////////////////////////////////////////////////
//通過改變TIM3->CCR2的值來改變占空比,從而控制LED0的亮度
#define LED0_PWM_VAL TIM3->CCR2
void Timerx_Init(u16 arr,u16 psc);
void PWM_Init(u16 arr,u16 psc);
#endif
usart.h
#ifndef __USART_H
#define __USART_H
#include
#include "stdio.h"
//////////////////////////////////////////////////////////////////////////////////
//本程序只供學(xué)習(xí)使用,未經(jīng)作者許可,不得用于其它任何用途
//Mini STM32開發(fā)板
//串口1初始化
//正點(diǎn)原子@ALIENTEK
//技術(shù)論壇:www.openedv.com
//修改日期:2010/5/27
//版本:V1.3
//版權(quán)所有,盜版必究。
//Copyright(C) 正點(diǎn)原子 2009-2019
//All rights reserved
//********************************************************************************
//V1.3修改說明
//支持適應(yīng)不同頻率下的串口波特率設(shè)置.
//加入了對printf的支持
//增加了串口接收命令功能.
//修正了printf第一個(gè)字符丟失的bug
//////////////////////////////////////////////////////////////////////////////////
extern u8 USART_RX_BUF[64]; //接收緩沖,最大63個(gè)字節(jié).末字節(jié)為換行符
extern u8 USART_RX_STA; //接收狀態(tài)標(biāo)記
extern char imgCenterX[5];
extern char imgCenterY[5];
extern int imgCenterX0,imgCenterX1;
extern int imgCenterY0,imgCenterY1;
//如果想串口中斷接收,請不要注釋以下宏定義
#define EN_USART1_RX //使能串口1接收
#define EN_USART2_RX //使能串口2接收
#define EN_USART3_RX //使能串口3接收
void uart_init(u32 pclk2,u32 bound);
#endif
usart.c
#include "sys.h"
#include "usart.h"
//////////////////////////////////////////////////////////////////////////////////
//本程序只供學(xué)習(xí)使用,未經(jīng)作者許可,不得用于其它任何用途
//Mini STM32開發(fā)板
//串口1初始化
//正點(diǎn)原子@ALIENTEK
//技術(shù)論壇:www.openedv.com
//修改日期:2010/5/27
//版本:V1.3
//版權(quán)所有,盜版必究。
//Copyright(C) 正點(diǎn)原子 2009-2019
//All rights reserved
//********************************************************************************
//V1.3修改說明
//支持適應(yīng)不同頻率下的串口波特率設(shè)置.
//加入了對printf的支持
//增加了串口接收命令功能.
//修正了printf第一個(gè)字符丟失的bug
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////
//加入以下代碼,支持printf函數(shù),而不需要選擇use MicroLIB
#if 1
#pragma import(__use_no_semihosting)
//標(biāo)準(zhǔn)庫需要的支持函數(shù)
struct __FILE
{
int handle;
/* Whatever you require here. If the only file you are using is */
/* standard output using printf() for debugging, no file handling */
/* is required. */
};
/* FILE is typedef’ d in stdio.h. */
FILE __stdout;
//定義_sys_exit()以避免使用半主機(jī)模式
_sys_exit(int x)
{
x = x;
}
//重定義fputc函數(shù),因?yàn)檫@個(gè)串口在ministm32上定義為PA9與PA10 與USB轉(zhuǎn)串口的芯片 連接 因此便于與PC機(jī)通訊,方便通過串口助手調(diào)試,所以不再重定義為其他串口輸出
int fputc(int ch, FILE *f)
{
while((USART1->SR&0X40)==0);//循環(huán)發(fā)送,直到發(fā)送完畢
USART1->DR = (u8) ch;
return ch;
}
////自己的重定義fputc函數(shù)
//我們還是定義USART1作為printf函數(shù)的重定義 輸出串口,但是用USART3進(jìn)行l(wèi)inux的串口輸入
//int fputc(int ch, FILE *f)
//{
// while((USART3->SR&0X40)==0);//循環(huán)發(fā)送,直到發(fā)送完畢
// USART3->DR = (u8) ch;
// return ch;
//}
#endif
//在stm32中,串口即用GPIO的復(fù)用功能輸出 由下面鏈接可以看出,
//http://download.csdn.net/detail/bolvtin/8867933
//PA9--USART1_TX 輸出 PA10--USART1_RX 輸入
//PA2--USART2_TX 輸出 PA3--USART2_RX 輸入
//PB10--USART3_TX 輸出;PB11--USART3_RX 輸入
/********************************************************************************/
//這里本來是用 串口1既不停地接收另一個(gè)PC機(jī)B的串口數(shù)據(jù),并且在程序里再不斷把數(shù)據(jù)發(fā)送給PC機(jī)A(上面有串口調(diào)試助手,以觀察數(shù)據(jù))的
//但是發(fā)現(xiàn),串口1在不斷接收的同時(shí),如果不停地再往外發(fā),數(shù)據(jù)就會(huì)丟失很多,導(dǎo)致程序錯(cuò)誤,
//因此設(shè)置為,從串口3接收PC機(jī)B的數(shù)據(jù),從串口1發(fā)送給PC機(jī)A的串口調(diào)試助手以觀察數(shù)據(jù)
//#ifdef EN_USART1_RX //如果使能了接收
////串口1中斷服務(wù)程序
////注意,讀取USARTx->SR能避免莫名其妙的錯(cuò)誤
//u8 USART_RX_BUF[64]; //接收緩沖,最大64個(gè)字節(jié).
////接收狀態(tài)
////bit7,接收完成標(biāo)志
////bit6,接收到0x0d
////bit5~0,接收到的有效字節(jié)數(shù)目
//u8 USART_RX_STA=0; //接收狀態(tài)標(biāo)記
//
//char imgCenterX[5];
//char imgCenterY[5];
//
//int imgCenterX0=320,imgCenterX1;//對應(yīng)的圖片為寬*高=640*480的
//int imgCenterY0=240,imgCenterY1;
//
//void USART1_IRQHandler(void)
//{
// u8 res;
// if(USART1->SR&(1<<5))//接收到數(shù)據(jù)
// {
// res=USART1->DR;
// if((USART_RX_STA&0x80)==0)//接收未完成
// {
// //if(USART_RX_STA&0x40)//接收到了0x0d,把USART_RX_STA設(shè)置為0100 0000
// if(USART_RX_STA&0x40)//接收到了$美金符號 王博
// {
// //if(res!=0x0a)USART_RX_STA=0;//接收錯(cuò)誤,重新開始
// if(res!=0x24)USART_RX_STA=0;//接收錯(cuò)誤,重新開始
// else
// {
//
// USART_RX_STA|=0x80; //接收完成了
// imgCenterX[0]=USART_RX_BUF[14]; //第15個(gè)字節(jié)
// imgCenterX[1]=USART_RX_BUF[15];
// imgCenterX[2]=USART_RX_BUF[16];
// imgCenterX[3]=USART_RX_BUF[17];
//
// imgCenterY[0]=USART_RX_BUF[36];
// imgCenterY[1]=USART_RX_BUF[37];
// imgCenterY[2]=USART_RX_BUF[38];
// imgCenterY[3]=USART_RX_BUF[39];
//
// imgCenterX1=atoi(imgCenterX);
// //printf("%dn",imgCenterX1);
//
// imgCenterY1=atoi(imgCenterY);
// //printf("%dn",imgCenterY1);
//
// }
// }else //還沒收到0X0D
// {
// //if(res==0x0d)USART_RX_STA|=0x40;
// if(res==0x24)USART_RX_STA|=0x40;
// else
// {
// USART_RX_BUF[USART_RX_STA&0X3F]=res;
// USART_RX_STA++;
// if(USART_RX_STA>63)USART_RX_STA=0;//接收數(shù)據(jù)錯(cuò)誤,重新開始接收
// }
// }
// }
// }
//}
//#endif
/********************************************************************************/
//mini stm32 串口2
#ifdef EN_USART2_RX //如果使能了接收
//串口1中斷服務(wù)程序
//注意,讀取USARTx->SR能避免莫名其妙的錯(cuò)誤
u8 USART_RX_BUF[64]; //接收緩沖,最大64個(gè)字節(jié).
//接收狀態(tài)
//bit7,接收完成標(biāo)志
//bit6,接收到0x0d
//bit5~0,接收到的有效字節(jié)數(shù)目
u8 USART_RX_STA=0; //接收狀態(tài)標(biāo)記
char imgCenterX[5];
char imgCenterY[5];
int imgCenterX0=320,imgCenterX1=320;//對應(yīng)的圖片為寬*高=640*480的
int imgCenterY0=240,imgCenterY1=240;
void USART2_IRQHandler(void)
{
u8 res;
if(USART2->SR&(1<<5))//接收到數(shù)據(jù)
{
res=USART2->DR;
if((USART_RX_STA&0x80)==0)//接收未完成
{
//if(USART_RX_STA&0x40)//接收到了0x0d,把USART_RX_STA設(shè)置為0100 0000
if(USART_RX_STA&0x40)//接收到了$美金符號 tinbo
{
//if(res!=0x0a)USART_RX_STA=0;//接收錯(cuò)誤,重新開始
if(res!=0x24)USART_RX_STA=0;//接收錯(cuò)誤,重新開始
else
{
USART_RX_STA|=0x80; //接收完成了
imgCenterX[0]=USART_RX_BUF[14]; //第15個(gè)字節(jié)
imgCenterX[1]=USART_RX_BUF[15];
imgCenterX[2]=USART_RX_BUF[16];
imgCenterX[3]=USART_RX_BUF[17];
imgCenterY[0]=USART_RX_BUF[36];
imgCenterY[1]=USART_RX_BUF[37];
imgCenterY[2]=USART_RX_BUF[38];
imgCenterY[3]=USART_RX_BUF[39];
imgCenterX1=atoi(imgCenterX);
//printf("%dn",imgCenterX1);
imgCenterY1=atoi(imgCenterY);
//printf("%dn",imgCenterY1);
}
}else //還沒收到0X0D
{
//if(res==0x0d)USART_RX_STA|=0x40;
if(res==0x24)USART_RX_STA|=0x40;
else
{
USART_RX_BUF[USART_RX_STA&0X3F]=res;
USART_RX_STA++;
if(USART_RX_STA>63)USART_RX_STA=0;//接收數(shù)據(jù)錯(cuò)誤,重新開始接收
}
}
}
}
else
{
}
}
#endif
/********************************************************************************/
//mini stm32 串口3
//#ifdef EN_USART3_RX //如果使能了接收
////串口1中斷服務(wù)程序
////注意,讀取USARTx->SR能避免莫名其妙的錯(cuò)誤
//u8 USART_RX_BUF[64]; //接收緩沖,最大64個(gè)字節(jié).
////接收狀態(tài)
////bit7,接收完成標(biāo)志
////bit6,接收到0x0d
////bit5~0,接收到的有效字節(jié)數(shù)目
//u8 USART_RX_STA=0; //接收狀態(tài)標(biāo)記
//
//char imgCenterX[5];
//char imgCenterY[5];
//
//int imgCenterX0=320,imgCenterX1=320;//對應(yīng)的圖片為寬*高=640*480的
//int imgCenterY0=240,imgCenterY1=240;
//
//void USART3_IRQHandler(void)
//{
// u8 res;
// if(USART3->SR&(1<<5))//接收到數(shù)據(jù)
// {
// res=USART3->DR;
// if((USART_RX_STA&0x80)==0)//接收未完成
// {
// //if(USART_RX_STA&0x40)//接收到了0x0d,把USART_RX_STA設(shè)置為0100 0000
// if(USART_RX_STA&0x40)//接收到了$美金符號 王博
// {
// //if(res!=0x0a)USART_RX_STA=0;//接收錯(cuò)誤,重新開始
// if(res!=0x24)USART_RX_STA=0;//接收錯(cuò)誤,重新開始
// else
// {
//
// USART_RX_STA|=0x80; //接收完成了
// imgCenterX[0]=USART_RX_BUF[14]; //第15個(gè)字節(jié)
// imgCenterX[1]=USART_RX_BUF[15];
// imgCenterX[2]=USART_RX_BUF[16];
// imgCenterX[3]=USART_RX_BUF[17];
//
// imgCenterY[0]=USART_RX_BUF[36];
// imgCenterY[1]=USART_RX_BUF[37];
// imgCenterY[2]=USART_RX_BUF[38];
// imgCenterY[3]=USART_RX_BUF[39];
//
// imgCenterX1=atoi(imgCenterX);
// //printf("%dn",imgCenterX1);
//
// imgCenterY1=atoi(imgCenterY);
// //printf("%dn",imgCenterY1);
//
// }
// }else //還沒收到0X0D
// {
// //if(res==0x0d)USART_RX_STA|=0x40;
// if(res==0x24)USART_RX_STA|=0x40;
// else
// {
// USART_RX_BUF[USART_RX_STA&0X3F]=res;
// USART_RX_STA++;
// if(USART_RX_STA>63)USART_RX_STA=0;//接收數(shù)據(jù)錯(cuò)誤,重新開始接收
// }
// }
// }
// }
// else
// {
//
// }
//}
//#endif
/********************************************************************************/
//初始化IO 串口
//pclk2:PCLK2時(shí)鐘頻率(Mhz)
//bound:波特率
//CHECK OK
//091209
void uart_init(u32 pclk2,u32 bound)
{
float temp;
u16 mantissa;
u16 fraction;
float temp2;
u16 mantissa2;
u16 fraction2;
float temp3;
u16 mantissa3;
u16 fraction3;
//總體是3部分
//1、使能串口1時(shí)鐘。但是因?yàn)橛玫搅薌PIO口,所以需要使能GPIO的時(shí)鐘,這里假設(shè)使能了A、B、C、D4個(gè)GPIO外設(shè),包括了GPIO口的3個(gè)步驟
//2、配置寄存器,配置波特率、停止位、校驗(yàn)位等
//3、串口使能,接收緩沖區(qū)非空中斷使能
/********************************************************************************/
//串口1 的初始化
temp=(float)(pclk2*1000000)/(bound*16);//得到USARTDIV
mantissa=temp; //得到整數(shù)部分
fraction=(temp-mantissa)*16; //得到小數(shù)部分
mantissa<<=4;
mantissa+=fraction;
RCC->APB2ENR|=1<<2; //使能PORTA口時(shí)鐘
RCC->APB2ENR|=1<<14; //使能串口1時(shí)鐘
GPIOA->CRH&=0XFFFFF00F;
GPIOA->CRH|=0X000008B0;//IO狀態(tài)設(shè)置
RCC->APB2RSTR|=1<<14; //復(fù)位串口1
RCC->APB2RSTR&=~(1<<14);//停止復(fù)位
//波特率設(shè)置
USART1->BRR=mantissa; // 波特率設(shè)置
USART1->CR1|=0X200C; //1位停止,無校驗(yàn)位.
#ifdef EN_USART1_RX //如果使能了接收
//使能接收中斷
USART1->CR1|=1<<8; //PE中斷使能
USART1->CR1|=1<<5; //接收緩沖區(qū)非空中斷使能
MY_NVIC_Init(3,3,USART1_IRQChannel,2);//組2,最低優(yōu)先級
#endif
/********************************************************************************/
//串口2 的初始化
//PORTA口時(shí)鐘 //串口2對應(yīng)的Tx為PA2 RX為PA3
temp2=(float)(pclk2/2*1000000)/(bound*16);//得到USARTDIV
mantissa2=temp2; //得到整數(shù)部分
fraction2=(temp2-mantissa2)*16; //得到小數(shù)部分
mantissa2<<=4;
mantissa2+=fraction2;
RCC->APB2ENR|=1<<2; //使能PORTA口時(shí)鐘 //串口2對應(yīng)的Tx為PA2 RX為PA3
RCC->APB1ENR|=1<<17; //使能串口2時(shí)鐘
GPIOA->CRL&=0XFFFF00FF; //設(shè)置PC10為輸出模式 PC11為輸入模式
GPIOA->CRL|=0X00008B00;//IO狀態(tài)設(shè)置
RCC->APB1RSTR|=1<<17; //復(fù)位串口3
RCC->APB1RSTR&=~(1<<17);//停止復(fù)位
//波特率設(shè)置
USART2->BRR=mantissa2; // 波特率設(shè)置 串口2-5使用的晶振都是36Mhz的 串口2~5使用的是pclk1,為36M,而不是串口1的72M
USART2->CR1|=0X200C; //1位停止,無校驗(yàn)位.
#ifdef EN_USART2_RX //如果使能了接收
//使能接收中斷
USART2->CR1|=1<<8; //PE中斷使能
USART2->CR1|=1<<5; //接收緩沖區(qū)非空中斷使能
MY_NVIC_Init(3,3,USART2_IRQChannel,1);//組1,最低優(yōu)先級
#endif
/********************************************************************************/
//串口3 的初始化
temp3=(float)(pclk2/2*1000000)/(bound*16);//得到USARTDIV
mantissa3=temp3; //得到整數(shù)部分
fraction3=(temp3-mantissa3)*16; //得到小數(shù)部分
mantissa3<<=4;
mantissa3+=fraction3;
RCC->APB1ENR|=1<<3; //使能PORTC口時(shí)鐘 //串口3對應(yīng)的Tx為PB10 RX為PB11
RCC->APB1ENR|=1<<18; //使能串口3時(shí)鐘
GPIOB->CRH&=0XFFFF00FF; //設(shè)置PB10為輸出模式 PB11為輸入模式
GPIOB->CRH|=0X00008B00;//IO狀態(tài)設(shè)置
RCC->APB1RSTR|=1<<18; //復(fù)位串口3
RCC->APB1RSTR&=~(1<<18);//停止復(fù)位
//波特率設(shè)置
USART3->BRR=mantissa3; // 波特率設(shè)置 串口2-5使用的晶振都是36Mhz的 串口2~5使用的是pclk1,為36M,而不是串口1的72M
USART3->CR1|=0X200C; //1位停止,無校驗(yàn)位.
#ifdef EN_USART3_RX //如果使能了接收
//使能接收中斷
USART3->CR1|=1<<8; //PE中斷使能
USART3->CR1|=1<<5; //接收緩沖區(qū)非空中斷使能
MY_NVIC_Init(3,3,USART3_IRQChannel,1);//組1,最低優(yōu)先級
#endif
}
timer.h
#ifndef __TIMER_H
#define __TIMER_H
#include "sys.h"
//////////////////////////////////////////////////////////////////////////////////
//本程序只供學(xué)習(xí)使用,未經(jīng)作者許可,不得用于其它任何用途
//Mini STM32開發(fā)板
//通用定時(shí)器 驅(qū)動(dòng)代碼
//正點(diǎn)原子@ALIENTEK
//技術(shù)論壇:www.openedv.com
//修改日期:2010/12/03
//版本:V1.0
//版權(quán)所有,盜版必究。
//Copyright(C) 正點(diǎn)原子 2009-2019
//All rights reserved
//////////////////////////////////////////////////////////////////////////////////
//通過改變TIM3->CCR2的值來改變占空比,從而控制LED0的亮度
#define LED0_PWM_VAL TIM3->CCR2
void Timerx_Init(u16 arr,u16 psc);
void PWM_Init(u16 arr,u16 psc);
#endif
timer.c
#include "timer.h"
#include "led.h"
//////////////////////////////////////////////////////////////////////////////////
//本程序只供學(xué)習(xí)使用,未經(jīng)作者許可,不得用于其它任何用途
//Mini STM32開發(fā)板
//通用定時(shí)器 驅(qū)動(dòng)代碼
//正點(diǎn)原子@ALIENTEK
//技術(shù)論壇:www.openedv.com
//修改日期:2010/12/03
//版本:V1.0
//版權(quán)所有,盜版必究。
//Copyright(C) 正點(diǎn)原子 2009-2019
//All rights reserved
//////////////////////////////////////////////////////////////////////////////////
//定時(shí)器3中斷服務(wù)程序
void TIM3_IRQHandler(void)
{
if(TIM3->SR&0X0001)//溢出中斷
{
LED1=!LED1;
}
TIM3->SR&=~(1<<0);//清除中斷標(biāo)志位
}
//通用定時(shí)器中斷初始化
//這里時(shí)鐘選擇為APB1的2倍,而APB1為36M
//arr:自動(dòng)重裝值。
//psc:時(shí)鐘預(yù)分頻數(shù)
//這里使用的是定時(shí)器3!
void Timerx_Init(u16 arr,u16 psc)
{
RCC->APB1ENR|=1<<1;//TIM3時(shí)鐘使能
TIM3->ARR=arr; //設(shè)定計(jì)數(shù)器自動(dòng)重裝值//剛好1ms
TIM3->PSC=psc; //預(yù)分頻器7200,得到10Khz的計(jì)數(shù)時(shí)鐘
//這兩個(gè)東東要同時(shí)設(shè)置才可以使用中斷
TIM3->DIER|=1<<0; //允許更新中斷
TIM3->DIER|=1<<6; //允許觸發(fā)中斷
TIM3->CR1|=0x01; //使能定時(shí)器3
MY_NVIC_Init(1,3,TIM3_IRQChannel,2);//搶占1,子優(yōu)先級3,組2
}
//TIM3 PWM部分
//正點(diǎn)原子@ALIENTEK
//2010/6/2
//PWM輸出初始化
//arr:自動(dòng)重裝值
//psc:時(shí)鐘預(yù)分頻數(shù)
void PWM_Init(u16 arr,u16 psc)
{
/********************************************************************************/
//總體是3部分
//1、使能定時(shí)器時(shí)鐘,因?yàn)镻WM是由定時(shí)器產(chǎn)生的。
// 其實(shí)這里用到了GPIOA的引腳,因此也需要使能GPIOA的時(shí)鐘的,但是在led.c文件中,已經(jīng)設(shè)置過了,所以這里省略了
// 另外這里使用的GPIO輸出PWM是復(fù)用,所以需要配置GPIO口的默認(rèn)復(fù)用功能,這里請注意,一定是默認(rèn)的復(fù)用功能,可以查看led.c中的3個(gè)步驟
//2、配置定時(shí)器的配置,TIM3->結(jié)構(gòu)后的,是對定時(shí)器3的配置
//3、使能定時(shí)器外設(shè),TIM3->CR1|=0x01;
//此部分需手動(dòng)修改IO口設(shè)置
RCC->APB1ENR|=1<<1; //TIM3時(shí)鐘使能
//下面這兩句僅僅是為了,用跳帽把PA7與PA8連接起來,用led燈來觀察PWM輸出,可以沒有的
GPIOA->CRH&=0XFFFFFFF0;//PA8輸出
GPIOA->CRH|=0X00000004;//浮空輸入 這里的浮空輸入是為了防止干擾PA8的輸出,因?yàn)镻A8在ministm32上是連接的led燈
GPIOA->CRL&=0X0FFFFFFF;//PA7輸出
GPIOA->CRL|=0XB0000000;//復(fù)用功能輸出
GPIOA->ODR|=1<<7;//PA7上拉
TIM3->ARR=arr;//設(shè)定計(jì)數(shù)器自動(dòng)重裝值
TIM3->PSC=psc;//預(yù)分頻器不分頻
//TIM3->CCMR1|=7<<12; //CH2 PWM2模式 這個(gè)作用在板子上的燈DS0
TIM3->CCMR1|=6<<12; //CH2 PWM2模式 與上面一句的極性相反 如果用這個(gè)控制舵機(jī),請使用這個(gè)PWM,輸出正電平方波
TIM3->CCMR1|=1<<11; //CH2預(yù)裝載使能
TIM3->CCER|=1<<4; //OC2 輸出使能
TIM3->CR1=0x8000; //ARPE使能
TIM3->CR1|=0x01; //使能定時(shí)器3
/********************************************************************************/
//通用定時(shí)器4 1通道(PB6)和2通道(PB7)
RCC->APB1ENR|=1<<2;//TIM4時(shí)鐘使能
RCC->APB2ENR|=1<<3;//這里必須有這一個(gè)GPIO口的使能,GPIOA已經(jīng)在led.c中定義過了,可是GPIO 的B口還沒有
GPIOB->CRL&=0X00FFFFFF;//清掉PB7 PB6位原來的設(shè)置,同時(shí)不影響其他位的設(shè)置
GPIOB->CRL|=0XBB000000;//復(fù)用功能輸出 PB7的默認(rèn)復(fù)用功能為 TIM4的2通道
GPIOB->ODR|=1<<7;//PB7
GPIOB->ODR|=1<<6;//PB6
TIM4->ARR=arr;//設(shè)定計(jì)數(shù)器自動(dòng)重裝值
TIM4->PSC=psc;//預(yù)分頻器不分頻
//這里進(jìn)行說明,CCMR1寄存器是配置模式的,總共可以設(shè)置為7中模式,CCMR1控制CH1和CH2 CCMR2控制CH3和CH4
//TIM4->CCMR1|=7<<12; //
TIM4->CCMR1|=6<<12; //PB7的默認(rèn)復(fù)用功能為 TIM4的2通道 CH2 PWM2模式且極性為正電平方波
TIM4->CCMR1|=6<<4; //CH1 PWM2模式
TIM4->CCMR1|=1<<11; //CH2預(yù)裝載使能
TIM4->CCMR1|=1<<3; //ch1預(yù)裝載使能 是PB6口
TIM4->CCER|=1<<0; //輸出使能 這個(gè)寄存器控制著各個(gè)輸入輸出通道的開關(guān),因此如果要有輸出必須使能
TIM4->CCER|=1<<4; //輸出使能
TIM4->CR1=0x8000; //ARPE使能
TIM4->CR1|=0x01; //使能定時(shí)器4
}
上一篇:STM32動(dòng)態(tài)更改PWM波頻率和占空比
下一篇:STM32之使用PWM控制多路舵機(jī)
推薦閱讀
史海拾趣
設(shè)計(jì)資源 培訓(xùn) 開發(fā)板 精華推薦
- Microchip 升級數(shù)字信號控制器(DSC)產(chǎn)品線 推出PWM 分辨率和 ADC 速度業(yè)界領(lǐng)先的新器件
- 意法半導(dǎo)體STM32MP23x:突破成本限制的工業(yè)AI應(yīng)用核心
- 意法半導(dǎo)體推出用于匹配遠(yuǎn)距離無線微控制器STM32WL33的集成的匹配濾波芯片
- ESP32開發(fā)板連接TFT顯示屏ST7789跳坑記
- 如何讓ESP32支持analogWrite函數(shù)
- LGVL配合FreeType為可變字體設(shè)置字重-ESP32篇
- 使用樹莓派進(jìn)行 ESP32 Jtag 調(diào)試
- ESP32怎么在SPIFFS里面存儲(chǔ)html,css,js文件,以及網(wǎng)頁和arduino的通訊
- ESP32 freeRTOS使用測試
- 2025研華智能系統(tǒng)產(chǎn)業(yè)伙伴峰會(huì)成功舉辦
- 意法半導(dǎo)體公布2025年第二季度財(cái)報(bào)和電話會(huì)議時(shí)間安排
- 利用人工智能提升車間生產(chǎn)效率
- 方案分享 | ARXML 規(guī)則下 ECU 總線通訊與 ADTF 測試方案
- 車載SerDes產(chǎn)業(yè)起飛!國產(chǎn)新品密集炸場
- 出貨量激增1.34倍! 5G車規(guī)模組成標(biāo)配,三大廠商新品同臺(tái)競技
- 6月新能源市場:零跑創(chuàng)新高;比亞迪海外突破;理想滑坡
- 基于中科芯車規(guī)MCU的LED矩陣大燈應(yīng)用方案
- 蘋果被判侵犯3G專利,需向西班牙公司TOT賠償1.1億美元
- 從設(shè)計(jì)概念到 FPGA 原型僅需數(shù)分鐘,印度 InCore 完成 SoC Generator 平臺(tái)硅驗(yàn)證
- 秋風(fēng)送爽,你來答題我送禮!看Maxim 深入淺出低功耗處理器視頻精彩為您呈現(xiàn)!
- EEWORLD社區(qū)月度獎(jiǎng)勵(lì),贈(zèng)E金幣!
- 一起“充電”,DIY自己專屬應(yīng)急燈
- 為你點(diǎn)贊——我最愛有“干貨”的博文
- 兆易GD32450I-EVAL免費(fèi)測評試用
- Vicor 白皮書下載有禮 | 在48V架構(gòu)中使用高密度功率轉(zhuǎn)換器構(gòu)建更好的機(jī)器人
- STM32全國巡回研討會(huì)?。ㄗ哌M(jìn)11城,9/12-10/27)
- 3小時(shí)實(shí)戰(zhàn)+剖析:TI工程師手把手帶你全面入門MSP430(限量售$4.3開發(fā)套件,助你參與動(dòng)手實(shí)驗(yàn))
- 【EEWORLD第二十九屆】2011年08月社區(qū)明星人物揭曉!
- 求助各位大俠看看這是什么單片機(jī)
- MSP430F5438學(xué)習(xí)筆記 初始化XT1
- 學(xué)習(xí)LINUX需要哪些基礎(chǔ)?
- 下載中心常見問題解答
- 同一個(gè)函數(shù)調(diào)用5次為何不行?請教
- 電子血壓計(jì)的氣泵氣閥電路部分
- 【有獎(jiǎng)下載活動(dòng)】ADI有獎(jiǎng)下載活動(dòng)之24:ADI公司醫(yī)療X射線成像解決方案
- 請教老師們:自已寫的winCE驅(qū)動(dòng)程序被加載后,馬上又被卸載了?
- TI M4(Cortex M4) MCU DMA 操作
- 鴻業(yè)同行科技有限公司招聘員工?。。。?/span>