Because of the project needs, I learned about the GPIO, serial port, PWM, and interrupt parts of stm32. Here is a summary for us to learn together. All programs have been tested in practice and the output is correct.
Paste the configuration program of GPIO, serial port, PWM (timer) as follows
1. Enable the peripheral clock: APB1ENR, APB2ENR
2. Configuration register or control register. When configuring the stm32 peripheral, you must enable the clock of the peripheral at any time! And each control register is likely to include 1 mode register, 2 enable register, and 3 may be what we think of as data register or content register.
3. Enable peripherals. Even if configured, if you don't enable the peripherals, they will never work, which is easy to forget.
Register configuration, please see
http://wenku.baidu.com/link?url=NE4LMJFepztwPxYEb0n72SMNZLTruz32JsEJNPAtcV9AcS9OpA6CoLrJGllXzW5relKtY2c8MBKWURnBdYZG_sNj7yg_JFo7cpdut4k1mzS
Since many pins of stm32 are multiplexed, they must be set to multiplex when configuring registers. Remember that multiplexing is the default multiplexing function. For reference documents, please check
http://download.csdn.net/detail/bolvtin/8867933
1. Peripheral clock register
RCC_APB1ENR (APB1 peripheral clock enable register)
RCC_APB2ENR (APB2 peripheral clock enable register)
RCC_APB2RSTR (APB2 peripheral reset register)
RCC_APB1RSTR (APB1 peripheral reset register)
There is a corresponding relationship between the peripheral enable register and the peripheral reset register, and the corresponding position corresponds to the clock enable and reset of the corresponding peripheral.
Note the following peripherals
1. GPIO--GPIOA, GPIOB, GPIOC, GPIOD, GPIOE, GPIOF, GPIOG clocks are all in the RCC_APB2ENR register
2. Serial port--USART1 clock is in the RCC_APB2ENR register
3. Timer-TIM1, TIM8 clocks are in RCC_APB2ENR register
1. Serial port - USART2, USART3, USART4, USART5 clocks are all in the RCC_APB1ENR register
2. Timer-TIM2, TIM3, TIM4, TIM5, TIM6, TIM7 clocks are all in the RCC_APB1ENR register, TIM2-TIM5 can generate PWM
Pay attention to the source of the timer's internal clock signal
When the clock division number of APB1 is set to 1, the clock of the general timer is the clock of APB1; when the clock division number of APB1 is set to 2, the clock of the general timer TIMx is twice that of APB1, that is, 72Mhz. The clock of advanced timer 1 and 8 comes from APB2, not APB1.
Procedure:
led.h
#ifndef __LED_H
#define __LED_H
#include "sys.h"
//Mini STM32 development board
//LED driver code
//Atom on point @ALIENTEK
//2010/5/27
//LED port definition
#define LED0 PAout(8) // PA8
#define LED1 PDout(2) // PD2
void LED_Init(void); //initialization
#endif
led.c
#include
#include "led.h"
///////////////////////////////////////////////////// ////////////////////////////////////
//This program is for learning purposes only and may not be used for any other purpose without the author's permission.
//Mini STM32 development board
//LED driver code
//Atom on point @ALIENTEK
//Technical forum: www.openedv.com
//Modification date: 2010/5/27
//Version: V1.0
//All rights reserved. Piracy will be prosecuted.
//Copyright(C) Zhengdian Atom 2009-2019
//All rights reserved
///////////////////////////////////////////////////// ////////////////////////////////////
//Initialize PA8 and PD2 as output ports and enable the clocks of these two ports
//LED IO initialization
/****************************************************** *******************************/
void LED_Init(void)
{
//The overall is 3 parts
//1. Enable the GPIO clock. Here, it is assumed that the 4 GPIO peripherals A, B, C, and D are enabled.
//2. Configure the register, whether it is input or output, the default definition, or the default multiplexing function
//3. Fill in the default data parameters. Here, the default output is high level.
RCC->APB2ENR|=1<<2; //Enable PORTA clock
RCC->APB2ENR|=1<<3; //Enable PORTB clock
RCC->APB2ENR|=1<<4; //Enable PORTC clock
RCC->APB2ENR|=1<<5; //Enable PORTD clock
GPIOA->CRH&=0XFFFFFFF0; //Clear the original setting of PA8 without affecting the settings of other bits. PA8 is connected to DS0 light on mini stm32
GPIOA->CRH|=0X00000003; //PA8 push-pull output
GPIOA->ODR|=1<<8; //PA8 output high
GPIOC->CRH&=0XFFF00FFF;
GPIOA->CRH|=0X00038000; //PC11 input PC12 output
GPIOA->ODR=1<<11; //PC11 pull-up
GPIOA->ODR|=1<<12; //PC.12 output high
GPIOD->CRL&=0XFFFFF0FF; //PD2 is connected to DS1 light on mini stm32
GPIOD->CRL|=0X00000300; //PD.2 push-pull output
GPIOD->ODR|=1<<2; //PD.2 output high
}
timer.h
#ifndef __TIMER_H
#define __TIMER_H
#include "sys.h"
///////////////////////////////////////////////////// ////////////////////////////////////
//This program is for learning purposes only and may not be used for any other purpose without the author's permission.
//Mini STM32 development board
//General timer driver code
//Atom on point @ALIENTEK
//Technical forum: www.openedv.com
//Modification date: 2010/12/03
//Version: V1.0
//All rights reserved. Piracy will be prosecuted.
//Copyright(C) Zhengdian Atom 2009-2019
//All rights reserved
///////////////////////////////////////////////////// ////////////////////////////////////
//Change the duty cycle by changing the value of TIM3->CCR2 to control the brightness of 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"
///////////////////////////////////////////////////// ////////////////////////////////////
//This program is for learning purposes only and may not be used for any other purpose without the author's permission.
//Mini STM32 development board
//Serial port 1 initialization
//Atom on point @ALIENTEK
//Technical forum: www.openedv.com
//Modification date: 2010/5/27
//Version: V1.3
//All rights reserved. Piracy will be prosecuted.
//Copyright(C) Zhengdian Atom 2009-2019
//All rights reserved
//************************************************ *********************************
//V1.3 modification instructions
//Support serial port baud rate settings at different frequencies.
//Added support for printf
//Added the serial port receiving command function.
//Fixed the bug that the first character of printf was lost
///////////////////////////////////////////////////// ////////////////////////////////////
extern u8 USART_RX_BUF[64]; //Receive buffer, maximum 63 bytes. The last byte is a line break character
extern u8 USART_RX_STA; //Receive status mark
extern char imgCenterX[5];
extern char imgCenterY[5];
extern int imgCenterX0,imgCenterX1;
extern int imgCenterY0,imgCenterY1;
//If you want the serial port to interrupt reception, please do not comment the following macro definition
#define EN_USART1_RX //Enable serial port 1 receiving
#define EN_USART2_RX //Enable serial port 2 receiving
#define EN_USART3_RX //Enable serial port 3 receiving
void uart_init(u32 pclk2,u32 bound);
#endif
usart.c
#include "sys.h"
#include "usart.h"
///////////////////////////////////////////////////// ////////////////////////////////////
//This program is for learning purposes only and may not be used for any other purpose without the author's permission.
//Mini STM32 development board
//Serial port 1 initialization
//Atom on point @ALIENTEK
//Technical forum: www.openedv.com
//Modification date: 2010/5/27
//Version: V1.3
//All rights reserved. Piracy will be prosecuted.
//Copyright(C) Zhengdian Atom 2009-2019
//All rights reserved
//************************************************ *********************************
//V1.3 modification instructions
//Support serial port baud rate settings at different frequencies.
//Added support for printf
//Added the serial port receiving command function.
//Fixed the bug that the first character of printf was lost
///////////////////////////////////////////////////// ////////////////////////////////////
///////////////////////////////////////////////////// /////////////////
//Add the following code to support the printf function without selecting use MicroLIB
#if 1
#pragma import(__use_no_semihosting)
//Support functions required by the standard library
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;
// define _sys_exit() to avoid using semihost mode
_sys_exit(int x)
{
x = x;
}
//Redefine fputc function, because this serial port is defined as PA9 and PA10 on minisTM32 and connected to the USB-to-serial port chip, it is convenient to communicate with the PC and debug through the serial port assistant, so it is not redefined to other serial port output
int fputc(int ch, FILE *f)
{
while((USART1->SR&0X40)==0);//Send in a loop until the sending is completed
USART1->DR = (u8)ch;
return ch;
}
////Own redefinition of fputc function
//We still define USART1 as the redefinition output serial port of the printf function, but use USART3 for Linux serial port input
//int fputc(int ch, FILE *f)
//{
// while((USART3->SR&0X40)==0); // Loop sending until the sending is completed
// USART3->DR = (u8) ch;
// return ch;
//}
#endif
//In stm32, the multiplexing function output of the serial port, i.e. GPIO, can be seen from the following link,
//http://download.csdn.net/detail/bolvtin/8867933
//PA9--USART1_TX output PA10--USART1_RX input
//PA2--USART2_TX output PA3--USART2_RX input
//PB10--USART3_TX output; PB11--USART3_RX input
/****************************************************** *******************************/
//Here, serial port 1 is used to continuously receive serial port data from another PC B, and then continuously send data to PC A in the program (there is a serial port debugging assistant on it to observe the data)
//But I found that if serial port 1 keeps sending data while receiving data, a lot of data will be lost, resulting in program errors.
//Therefore, it is set to receive data from PC B from serial port 3 and send it from serial port 1 to PC A's serial debugging assistant to observe the data
//#ifdef EN_USART1_RX //If reception is enabled
////Serial port 1 interrupt service routine
////Note that reading USARTx->SR can avoid inexplicable errors
//u8 USART_RX_BUF[64]; //Receive buffer, maximum 64 bytes.
////Receiving status
////bit7, receiving completion flag
////bit6, received 0x0d
////bit5~0, the number of valid bytes received
//u8 USART_RX_STA=0; //Receive status flag
//
//char imgCenterX[5];
//char imgCenterY[5];
//
//int imgCenterX0=320,imgCenterX1; //The corresponding image is width*height=640*480
//int imgCenterY0=240,imgCenterY1;
//
//void USART1_IRQHandler(void)
//{
// u8 res;
// if(USART1->SR&(1<<5))//Receive data
// {
//res=USART1->DR;
// if((USART_RX_STA&0x80)==0)//receiving is not completed
// {
// //if(USART_RX_STA&0x40) //Received 0x0d, set USART_RX_STA to 0100 0000
// if(USART_RX_STA&0x40) //Received the $US dollar symbol Wang Bo
// {
// //if(res!=0x0a)USART_RX_STA=0;//Receive error, restart
// if(res!=0x24)USART_RX_STA=0; //Receive error, restart
// else
// {
//
// USART_RX_STA|=0x80; //Receiving completed
// imgCenterX[0]=USART_RX_BUF[14]; //15th byte
// 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 //Has not received 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; //Receive data error, restart receiving
// }
// }
// }
// }
//}
//#endif
/****************************************************** *******************************/
//mini stm32 serial port 2
#ifdef EN_USART2_RX //If reception is enabled
//Serial port 1 interrupt service routine
//Note that reading USARTx->SR can avoid inexplicable errors
u8 USART_RX_BUF[64]; //Receive buffer, maximum 64 bytes.
//Receive status
//bit7, receiving completion flag
//bit6, received 0x0d
//bit5~0, the number of valid bytes received
u8 USART_RX_STA=0; //Receive status mark
char imgCenterX[5];
char imgCenterY[5];
int imgCenterX0=320,imgCenterX1=320; //The corresponding image is width*height=640*480
int imgCenterY0=240,imgCenterY1=240;
void USART2_IRQHandler(void)
{
u8 res;
if(USART2->SR&(1<<5))//Receive data
{
res=USART2->DR;
if((USART_RX_STA&0x80)==0)//receiving is not completed
{
//if(USART_RX_STA&0x40) //Received 0x0d, set USART_RX_STA to 0100 0000
if(USART_RX_STA&0x40) //Received $dollar symbol tinbo
{
//if(res!=0x0a)USART_RX_STA=0;//Receive error, restart
if(res!=0x24)USART_RX_STA=0; //Receive error, restart
else
{
USART_RX_STA|=0x80; //Receiving completed
imgCenterX[0]=USART_RX_BUF[14]; //15th byte
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 //Has not received 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; //Receive data error, restart receiving
}
}
}
}
else
{
}
}
#endif
/****************************************************** *******************************/
//mini stm32 serial port 3
//#ifdef EN_USART3_RX //If reception is enabled
////Serial port 1 interrupt service routine
////Note that reading USARTx->SR can avoid inexplicable errors
//u8 USART_RX_BUF[64]; //Receive buffer, maximum 64 bytes.
////Receiving status
////bit7, receiving completion flag
////bit6, received 0x0d
////bit5~0, the number of valid bytes received
//u8 USART_RX_STA=0; //Receive status flag
//
//char imgCenterX[5];
//char imgCenterY[5];
//
//int imgCenterX0=320,imgCenterX1=320; //The corresponding image is width*height=640*480
//int imgCenterY0=240,imgCenterY1=240;
//
//void USART3_IRQHandler(void)
//{
// u8 res;
// if(USART3->SR&(1<<5))//Receive data
// {
//res=USART3->DR;
// if((USART_RX_STA&0x80)==0)//receiving is not completed
// {
// //if(USART_RX_STA&0x40) //Received 0x0d, set USART_RX_STA to 0100 0000
// if(USART_RX_STA&0x40) //Received the $US dollar symbol Wang Bo
// {
// //if(res!=0x0a)USART_RX_STA=0;//Receive error, restart
// if(res!=0x24)USART_RX_STA=0; //Receive error, restart
// else
// {
//
// USART_RX_STA|=0x80; //Receiving completed
// imgCenterX[0]=USART_RX_BUF[14]; //15th byte
// 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 //Has not received 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; //Receive data error, restart receiving
// }
// }
// }
// }
// else
// {
//
// }
//}
//#endif
/****************************************************** *******************************/
// Initialize IO serial port
//pclk2: PCLK2 clock frequency (Mhz)
//bound: baud rate
//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;
//The overall is 3 parts
//1. Enable the serial port 1 clock. However, because the GPIO port is used, the GPIO clock needs to be enabled. Here, it is assumed that the 4 GPIO peripherals A, B, C, and D are enabled, including the 3 steps of the GPIO port
//2. Configure registers, configure baud rate, stop bit, check bit, etc.
//3. Enable the serial port and enable the receive buffer non-empty interrupt
/****************************************************** *******************************/
//Initialization of serial port 1
temp=(float)(pclk2*1000000)/(bound*16);//get USARTDIV
mantissa=temp; //get the integer part
fraction=(temp-mantissa)*16; //get the decimal part
mantissa<<=4;
mantissa+=fraction;
RCC->APB2ENR|=1<<2; //Enable PORTA clock
RCC->APB2ENR|=1<<14; //Enable serial port 1 clock
GPIOA->CRH&=0XFFFFF00F;
GPIOA->CRH|=0X000008B0; //IO status setting
RCC->APB2RSTR|=1<<14; //Reset serial port 1
RCC->APB2RSTR&=~(1<<14);//stop reset
//Baud rate setting
USART1->BRR=mantissa; // baud rate setting
USART1->CR1|=0X200C; //1-bit stop, no parity bit.
#ifdef EN_USART1_RX //If reception is enabled
// Enable receive interrupt
USART1->CR1|=1<<8; //PE interrupt enable
USART1->CR1|=1<<5; //Receive buffer not empty interrupt enable
MY_NVIC_Init(3,3,USART1_IRQChannel,2); //Group 2, lowest priority
#endif
/****************************************************** *******************************/
//Initialization of serial port 2
//PORTA port clock //Serial port 2 corresponds to Tx is PA2 RX is PA3
temp2=(float)(pclk2/2*1000000)/(bound*16);//get USARTDIV
mantissa2=temp2; //get the integer part
fraction2=(temp2-mantissa2)*16; //get the decimal part
mantissa2<<=4;
mantissa2+=fraction2;
RCC->APB2ENR|=1<<2; //Enable PORTA port clock //Serial port 2 corresponds to Tx PA2 RX PA3
RCC->APB1ENR|=1<<17; //Enable serial port 2 clock
GPIOA->CRL&=0XFFFF00FF; //Set PC10 to output mode and PC11 to input mode
GPIOA->CRL|=0X00008B00; //IO status setting
RCC->APB1RSTR|=1<<17; //Reset serial port 3
RCC->APB1RSTR&=~(1<<17);//stop reset
//Baud rate setting
USART2->BRR=mantissa2; // baud rate setting The crystal oscillators used by serial ports 2-5 are all 36Mhz. Serial ports 2~5 use pclk1, which is 36M, instead of 72M of serial port 1.
USART2->CR1|=0X200C; //1-bit stop, no parity bit.
#ifdef EN_USART2_RX //If reception is enabled
// Enable receive interrupt
USART2->CR1|=1<<8; //PE interrupt enable
USART2->CR1|=1<<5; //Receive buffer not empty interrupt enable
MY_NVIC_Init(3,3,USART2_IRQChannel,1); //Group 1, lowest priority
#endif
/****************************************************** *******************************/
//Initialization of serial port 3
temp3=(float)(pclk2/2*1000000)/(bound*16); //Get USARTDIV
mantissa3=temp3; //get the integer part
fraction3=(temp3-mantissa3)*16; //get the decimal part
mantissa3<<=4;
mantissa3+=fraction3;
RCC->APB1ENR|=1<<3; //Enable PORTC port clock //Serial port 3 corresponds to Tx PB10 RX PB11
RCC->APB1ENR|=1<<18; //Enable serial port 3 clock
GPIOB->CRH&=0XFFFF00FF; //Set PB10 to output mode and PB11 to input mode
GPIOB->CRH|=0X00008B00; //IO status setting
RCC->APB1RSTR|=1<<18; //Reset serial port 3
RCC->APB1RSTR&=~(1<<18);//stop reset
//Baud rate setting
USART3->BRR=mantissa3; // baud rate setting The crystal oscillators used by serial ports 2-5 are all 36Mhz. Serial ports 2~5 use pclk1, which is 36M, instead of 72M of serial port 1.
USART3->CR1|=0X200C; //1-bit stop, no parity bit.
#ifdef EN_USART3_RX //If reception is enabled
// Enable receive interrupt
USART3->CR1|=1<<8; //PE interrupt enable
USART3->CR1|=1<<5; //Receive buffer not empty interrupt enable
MY_NVIC_Init(3,3,USART3_IRQChannel,1); //Group 1, lowest priority
#endif
}
timer.h
#ifndef __TIMER_H
#define __TIMER_H
#include "sys.h"
///////////////////////////////////////////////////// ////////////////////////////////////
//This program is for learning purposes only and may not be used for any other purpose without the author's permission.
//Mini STM32 development board
//General timer driver code
//Atom on point @ALIENTEK
//Technical forum: www.openedv.com
//Modification date: 2010/12/03
//Version: V1.0
//All rights reserved. Piracy will be prosecuted.
//Copyright(C) Zhengdian Atom 2009-2019
//All rights reserved
///////////////////////////////////////////////////// ////////////////////////////////////
//Change the duty cycle by changing the value of TIM3->CCR2 to control the brightness of 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"
///////////////////////////////////////////////////// ////////////////////////////////////
//This program is for learning purposes only and may not be used for any other purpose without the author's permission.
//Mini STM32 development board
//General timer driver code
//Atom on point @ALIENTEK
//Technical forum: www.openedv.com
//Modification date: 2010/12/03
//Version: V1.0
//All rights reserved. Piracy will be prosecuted.
//Copyright(C) Zhengdian Atom 2009-2019
//All rights reserved
///////////////////////////////////////////////////// ////////////////////////////////////
//Timer 3 interrupt service routine
void TIM3_IRQHandler(void)
{
if(TIM3->SR&0X0001)//overflow interrupt
{
LED1=!LED1;
}
TIM3->SR&=~(1<<0); //Clear interrupt flag
}
//General timer interrupt initialization
//The clock here is selected to be twice that of APB1, and APB1 is 36M
//arr: automatically reload value.
//psc: clock pre-division number
//Timer 3 is used here!
void Timerx_Init(u16 arr,u16 psc)
{
RCC->APB1ENR|=1<<1; //TIM3 clock enable
TIM3->ARR=arr; //Set the counter to automatically reload the value //Exactly 1ms
TIM3->PSC=psc; //Prescaler 7200, get 10Khz counting clock
//These two things must be set at the same time to use the interrupt
TIM3->DIER|=1<<0; //Enable update interrupt
TIM3->DIER|=1<<6; //Enable trigger interrupt
TIM3->CR1|=0x01; //Enable timer 3
MY_NVIC_Init(1,3,TIM3_IRQChannel,2); //Preempt 1, subpriority 3, group 2
}
//TIM3 PWM part
//Atom on point @ALIENTEK
//2010/6/2
//PWM output initialization
//arr: automatically reload value
//psc: clock pre-division number
void PWM_Init(u16 arr,u16 psc)
{
/****************************************************** *******************************/
//The overall is 3 parts
//1. Enable the timer clock, because PWM is generated by the timer.
// Actually, the GPIOA pin is used here, so the GPIOA clock also needs to be enabled, but it has been set in the led.c file, so it is omitted here
// In addition, the GPIO output PWM used here is multiplexed, so you need to configure the default multiplexing function of the GPIO port. Please note that it must be the default multiplexing function. You can check the 3 steps in led.c
//2. Configure the timer configuration. After TIM3-> structure, it is the configuration of timer 3.
//3. Enable the timer peripheral, TIM3->CR1|=0x01;
//This part requires manual modification of IO port settings
RCC->APB1ENR|=1<<1; //TIM3 clock enable
//The following two sentences are just for connecting PA7 and PA8 with jumper caps and using LED lights to observe PWM output.
GPIOA->CRH&=0XFFFFFFF0; //PA8 output
GPIOA->CRH|=0X00000004; //Floating input The floating input here is to prevent interference with the output of PA8, because PA8 is connected to the LED light on minisTM32
GPIOA->CRL&=0X0FFFFFFF; //PA7 output
GPIOA->CRL|=0XB0000000; //Multiplexing function output
GPIOA->ODR|=1<<7; //PA7 pull-up
TIM3->ARR=arr; //Set the counter to automatically reload value
TIM3->PSC=psc; //Prescaler does not divide
//TIM3->CCMR1|=7<<12; //CH2 PWM2 mode This acts on the light DS0 on the board
TIM3->CCMR1|=6<<12; //CH2 PWM2 mode The polarity is opposite to the above sentence. If you use this to control the servo, please use this PWM to output a positive level square wave
TIM3->CCMR1|=1<<11; //CH2 preload enable
TIM3->CCER|=1<<4; //OC2 output enable
TIM3->CR1=0x8000; //ARPE enable
TIM3->CR1|=0x01; //Enable timer 3
/****************************************************** *******************************/
//General purpose timer 4 1 channel (PB6) and 2 channel (PB7)
RCC->APB1ENR|=1<<2; //TIM4 clock enable
RCC->APB2ENR|=1<<3; //This GPIO port must be enabled. GPIOA has been defined in led.c, but GPIO port B has not yet been defined.
GPIOB->CRL&=0X00FFFFFF; //Clear the original settings of PB7 and PB6 without affecting the settings of other bits
GPIOB->CRL|=0XBB000000; //Multiplexing function output The default multiplexing function of PB7 is 2 channels of TIM4
GPIOB->ODR|=1<<7;//PB7
GPIOB->ODR|=1<<6;//PB6
TIM4->ARR=arr; //Set the counter to automatically reload value
TIM4->PSC=psc; //Prescaler does not divide
//Here is an explanation, CCMR1 register is in configuration mode, a total of 7 modes can be set, CCMR1 controls CH1 and CH2 CCMR2 controls CH3 and CH4
//TIM4->CCMR1|=7<<12; //
TIM4->CCMR1|=6<<12; //The default multiplexing function of PB7 is TIM4's 2-channel CH2 PWM2 mode and the polarity is a positive level square wave
TIM4->CCMR1|=6<<4; //CH1 PWM2 mode
TIM4->CCMR1|=1<<11; //CH2 preload enable
TIM4->CCMR1|=1<<3; //ch1 preload enable is PB6 port
TIM4->CCER|=1<<0; //Output enable This register controls the switch of each input and output channel, so if there is output, it must be enabled
TIM4->CCER|=1<<4; //output enable
TIM4->CR1=0x8000; //ARPE enable
TIM4->CR1|=0x01; //Enable timer 4
}
Previous article:STM32 dynamically changes PWM wave frequency and duty cycle
Next article:STM32 uses PWM to control multiple servos
Recommended ReadingLatest update time:2024-11-15 17:03
- Popular Resources
- Popular amplifiers
- Siemens PLC Project Tutorial
- 西门子S7-12001500 PLC SCL语言编程从入门到精通 (北岛李工)
- Small AC Servo Motor Control Circuit Design (by Masaru Ishijima; translated by Xue Liang and Zhu Jianjun, by Masaru Ishijima, Xue Liang, and Zhu Jianjun)
- Intelligent Control Technology of Permanent Magnet Synchronous Motor (Written by Wang Jun)
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
- LED chemical incompatibility test to see which chemicals LEDs can be used with
- Application of ARM9 hardware coprocessor on WinCE embedded motherboard
- What are the key points for selecting rotor flowmeter?
- LM317 high power charger circuit
- A brief analysis of Embest's application and development of embedded medical devices
- Single-phase RC protection circuit
- stm32 PVD programmable voltage monitor
- Introduction and measurement of edge trigger and level trigger of 51 single chip microcomputer
- Improved design of Linux system software shell protection technology
- What to do if the ABB robot protection device stops
- Huawei's Strategic Department Director Gai Gang: The cumulative installed base of open source Euler operating system exceeds 10 million sets
- Download from the Internet--ARM Getting Started Notes
- Learn ARM development(22)
- Learn ARM development(21)
- Learn ARM development(20)
- Learn ARM development(19)
- Learn ARM development(14)
- Learn ARM development(15)
- Analysis of the application of several common contact parts in high-voltage connectors of new energy vehicles
- Wiring harness durability test and contact voltage drop test method
- Selling Raspberry Pi 3b+ with 7-inch display and camera, beaglebone black, nrf52840 original development board
- How to design amplifier circuits with different frequencies?
- Download the LTpowerPlanner System-Level Design Tool Quick Start Guide for free
- DB9 pin type: RS485 output signal and terminal pin assignment
- Loop-Powered 4mA to 20mA RTD Temperature Transmitter Reference Design with MSP430 Smart Analog Combo
- Can you guys answer my question about 74HC04?
- OFDR for short-range high-precision measurements
- FPGA instantiation issues
- EEWORLD University ---- MSP430 capacitive touch technology - waterproof Demo
- Study for the rise of China! Hainan student with full score chooses to enter Tsinghua University to make chips