wzh_hackster
Published

Distance-Controlled Model Car

No matter where you release, this model car will keep a constant distance from obstacle. Input capture, PWM output, control system model.

IntermediateFull instructions providedOver 1 day1,388
Distance-Controlled Model Car

Things used in this project

Hardware components

L298N dual motor controller module
×2
Ultrasonic Sensor - HC-SR04 (Generic)
Ultrasonic Sensor - HC-SR04 (Generic)
×1
DC Motor, 12 V
DC Motor, 12 V
×4
Alientek STM32F767 demoboard
×1

Story

Read more

Code

main.c

C/C++
#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "MOTOR.h"
#include "ULTRASONIC_METER.h"
#include "PID.h"

int main(void)
{
		int data_scaler=0;//variable used to filter
	
    Cache_Enable();                
    HAL_Init();				        
    Stm32_Clock_Init(432,25,2,9);    
    delay_init(216);                 
		uart_init(115200);		        
                        
    TIM3_PWM_Init(500-1,108-1); 
		TIM5_CH1_Cap_Init(0XFFFFFFFF,108-1);
		
		motor_initialize();
		trig_initialize();
		
	
		
    while(1)
    {
			
			
			trig_emit();
			delay_ms(5);
			
			pid_calculator();
			pid_controller();
			
			data_scaler++;
			if(data_scaler==9){// print only 1/10 data
			printf("%f %d\r\n",distance,duty_ratio);
			data_scaler=0;
			}

    } 
}

delay.c

C/C++
credit:www.alientek.com
#include "delay.h"
#include "sys.h"
//this file is open-source technical support from Alientek
//the function this file is providing delay function
#if SYSTEM_SUPPORT_OS
#include "includes.h"			 
#endif

static u32 fac_us=0;							

#if SYSTEM_SUPPORT_OS 	
static u16 fac_ms=0;							
#endif

#if SYSTEM_SUPPORT_OS							

#ifdef 	OS_CRITICAL_METHOD							
#define delay_osrunning		OSRunning			
#define delay_ostickspersec	OS_TICKS_PER_SEC	
#define delay_osintnesting 	OSIntNesting
#endif

#ifdef 	CPU_CFG_CRITICAL_METHOD						
#define delay_osrunning		OSRunning			
#define delay_ostickspersec	OSCfg_TickRate_Hz	
#define delay_osintnesting 	OSIntNestingCtr		
#endif


void delay_osschedlock(void)
{
#ifdef CPU_CFG_CRITICAL_METHOD   			
	OS_ERR err; 
	OSSchedLock(&err);						
#else										
	OSSchedLock();							
#endif
}

void delay_osschedunlock(void)
{	
#ifdef CPU_CFG_CRITICAL_METHOD   		
	OS_ERR err; 
	OSSchedUnlock(&err);				
#else										
	OSSchedUnlock();					
#endif
}

void delay_ostimedly(u32 ticks)
{
#ifdef CPU_CFG_CRITICAL_METHOD
	OS_ERR err; 
	OSTimeDly(ticks,OS_OPT_TIME_PERIODIC,&err);
#else
	OSTimeDly(ticks);				
#endif 
}
 

void SysTick_Handler(void)
{	
    HAL_IncTick();
	if(delay_osrunning==1)				
	{
		OSIntEnter();						
		OSTimeTick();       				            
		OSIntExit();       	 		
	}
}
#endif
			   

void delay_init(u8 SYSCLK)
{
#if SYSTEM_SUPPORT_OS 						
	u32 reload;
#endif
    HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);
	fac_us=SYSCLK;						   
#if SYSTEM_SUPPORT_OS 				 
	reload=SYSCLK;					      
	reload*=1000000/delay_ostickspersec;	 
											 
	fac_ms=1000/delay_ostickspersec;		    
	SysTick->CTRL|=SysTick_CTRL_TICKINT_Msk; 
	SysTick->LOAD=reload; 					 
	SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk;  
#endif 
}								    

#if SYSTEM_SUPPORT_OS 			 
     								   
void delay_us(u32 nus)
{		
	u32 ticks;
	u32 told,tnow,tcnt=0;
	u32 reload=SysTick->LOAD;		   	 
	ticks=nus*fac_us; 					 
	delay_osschedlock();				 
	told=SysTick->VAL;        			 
	while(1)
	{
		tnow=SysTick->VAL;	
		if(tnow!=told)
		{	    
			if(tnow<told)tcnt+=told-tnow; 
			else tcnt+=reload-tnow+told;	    
			told=tnow;
			if(tcnt>=ticks)break;		 
		}  
	};
	delay_osschedunlock(); 
}  
 
void delay_ms(u16 nms)
{	
	if(delay_osrunning&&delay_osintnesting==0)     
	{		 
		if(nms>=fac_ms)						 
		{ 
   			delay_ostimedly(nms/fac_ms);	 
		}
		nms%=fac_ms;					    
	}
	delay_us((u32)(nms*1000));				 
}
#else    
 
void delay_us(u32 nus)
{		
	u32 ticks;
	u32 told,tnow,tcnt=0;
	u32 reload=SysTick->LOAD;			     	 
	ticks=nus*fac_us; 					 
	told=SysTick->VAL;        				 
	while(1)
	{
		tnow=SysTick->VAL;	
		if(tnow!=told)
		{	    
			if(tnow<told)tcnt+=told-tnow; 
			else tcnt+=reload-tnow+told;	    
			told=tnow;
			if(tcnt>=ticks)break;		 
		}  
	};
}
 
void delay_ms(u16 nms)
{
	u32 i;
	for(i=0;i<nms;i++) delay_us(1000);
}

#endif

delay.h

C/C++
credit:www.alientek.com
#ifndef _DELAY_H
#define _DELAY_H
#include <sys.h>	  
//this file is open-source technical support from Alientek
//the function this file is providing delay function

void delay_init(u8 SYSCLK);
void delay_ms(u16 nms);
void delay_us(u32 nus);
#endif

usart.c

C/C++
credit:www.alientek.com
#include "usart.h"
//this file is open-source technical support from Alientek
//the function this file enable uart transmission
#if SYSTEM_SUPPORT_OS
#include "includes.h"					 
#endif
 
#if 1
#pragma import(__use_no_semihosting)             
                 
struct __FILE 
{ 
	int handle; 
}; 

FILE __stdout;       
   
void _sys_exit(int x) 
{ 
	x = x; 
} 
 
int fputc(int ch, FILE *f)
{ 	
	while((USART1->ISR&0X40)==0);   
	USART1->TDR=(u8)ch;      
	return ch;
}
#endif 

#if EN_USART1_RX   
 	
u8 USART_RX_BUF[USART_REC_LEN];    

u16 USART_RX_STA=0;     	

u8 aRxBuffer[RXBUFFERSIZE];
UART_HandleTypeDef UART1_Handler; 

void uart_init(u32 bound)
{	

	UART1_Handler.Instance=USART1;					  
	UART1_Handler.Init.BaudRate=bound;				  
	UART1_Handler.Init.WordLength=UART_WORDLENGTH_8B;   
	UART1_Handler.Init.StopBits=UART_STOPBITS_1;	   
	UART1_Handler.Init.Parity=UART_PARITY_NONE;		   
	UART1_Handler.Init.HwFlowCtl=UART_HWCONTROL_NONE;  
	UART1_Handler.Init.Mode=UART_MODE_TX_RX;		    
	HAL_UART_Init(&UART1_Handler);					  
	
	HAL_UART_Receive_IT(&UART1_Handler, (u8 *)aRxBuffer, RXBUFFERSIZE);
  
}


void HAL_UART_MspInit(UART_HandleTypeDef *huart)
{

	GPIO_InitTypeDef GPIO_Initure;
	
	if(huart->Instance==USART1)
	{
		__HAL_RCC_GPIOA_CLK_ENABLE();			
		__HAL_RCC_USART1_CLK_ENABLE();		
	
		GPIO_Initure.Pin=GPIO_PIN_9;		
		GPIO_Initure.Mode=GPIO_MODE_AF_PP;		
		GPIO_Initure.Pull=GPIO_PULLUP;		
		GPIO_Initure.Speed=GPIO_SPEED_FAST;	
		GPIO_Initure.Alternate=GPIO_AF7_USART1;	
		HAL_GPIO_Init(GPIOA,&GPIO_Initure);	 

		GPIO_Initure.Pin=GPIO_PIN_10;			
		HAL_GPIO_Init(GPIOA,&GPIO_Initure);	 
		
#if EN_USART1_RX
		HAL_NVIC_EnableIRQ(USART1_IRQn);			
		HAL_NVIC_SetPriority(USART1_IRQn,3,3);			
#endif	
	}

}

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	if(huart->Instance==USART1)
	{
		if((USART_RX_STA&0x8000)==0)
		{
			if(USART_RX_STA&0x4000)
			{
				if(aRxBuffer[0]!=0x0a)USART_RX_STA=0;
				else USART_RX_STA|=0x8000;	
			}
			else 
			{	
				if(aRxBuffer[0]==0x0d)USART_RX_STA|=0x4000;
				else
				{
					USART_RX_BUF[USART_RX_STA&0X3FFF]=aRxBuffer[0] ;
					USART_RX_STA++;
					if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;
				}		 
			}
		}

	}
}
 

void USART1_IRQHandler(void)                	
{ 
	u32 timeout=0;
    u32 maxDelay=0x1FFFF;
#if SYSTEM_SUPPORT_OS	 	
	OSIntEnter();    
#endif
	
	HAL_UART_IRQHandler(&UART1_Handler);
	
	timeout=0;
    while (HAL_UART_GetState(&UART1_Handler)!=HAL_UART_STATE_READY)
	{
        timeout++;
        if(timeout>maxDelay) break;		
	}
     
	timeout=0;
	while(HAL_UART_Receive_IT(&UART1_Handler,(u8 *)aRxBuffer, RXBUFFERSIZE)!=HAL_OK)
	{
        timeout++; 
        if(timeout>maxDelay) break;	
	}
#if SYSTEM_SUPPORT_OS	
	OSIntExit();  											 
#endif
} 
#endif	

usart.h

C/C++
credit:www.alientek.com
#ifndef _USART_H
#define _USART_H
#include "sys.h"
#include "stdio.h"	
//this file is open-source technical support from Alientek
//the function this file enable uart transmission
#define USART_REC_LEN  			200  	 
#define EN_USART1_RX 			1	 
	  	
extern u8  USART_RX_BUF[USART_REC_LEN];  
extern u16 USART_RX_STA;         	 
extern UART_HandleTypeDef UART1_Handler;  

#define RXBUFFERSIZE   1 
extern u8 aRxBuffer[RXBUFFERSIZE]; 

void uart_init(u32 bound);
#endif

ultrasonic meter.c

C/C++
#include "ULTRASONIC_METER.h"
#include "delay.h"

TIM_HandleTypeDef TIM5_Handler;
long long pecnt=0;//TIM5 period elapse counter
long long iccnt=0;//TIM5 input capture counter
int echo_switch=0;//determine input capture condition


void TIM5_CH1_Cap_Init(u32 arr,u16 psc)//initialization TIM5 channel 1
{   
		
		TIM_IC_InitTypeDef TIM5_CH1Config;  
			
		TIM5_Handler.Instance=TIM5;                          
		TIM5_Handler.Init.Prescaler=psc;                     
		TIM5_Handler.Init.CounterMode=TIM_COUNTERMODE_UP;    
		TIM5_Handler.Init.Period=arr;
		TIM5_Handler.Init.ClockDivision=TIM_CLOCKDIVISION_DIV1;
		HAL_TIM_IC_Init(&TIM5_Handler);

		TIM5_CH1Config.ICPolarity=TIM_ICPOLARITY_RISING;    
		TIM5_CH1Config.ICSelection=TIM_ICSELECTION_DIRECTTI;
		TIM5_CH1Config.ICPrescaler=TIM_ICPSC_DIV1;          
		TIM5_CH1Config.ICFilter=0;                          
		HAL_TIM_IC_ConfigChannel(&TIM5_Handler,&TIM5_CH1Config,TIM_CHANNEL_1);
		HAL_TIM_IC_Start_IT(&TIM5_Handler,TIM_CHANNEL_1);   //Enable capture interruption
		__HAL_TIM_ENABLE_IT(&TIM5_Handler,TIM_IT_UPDATE); 	//Enable period elapse interruption
}

void HAL_TIM_IC_MspInit(TIM_HandleTypeDef *htim)//callback by capture interruption initialization function
{
    GPIO_InitTypeDef GPIO_Initure;
    __HAL_RCC_TIM5_CLK_ENABLE();            
    __HAL_RCC_GPIOH_CLK_ENABLE();			
	
    GPIO_Initure.Pin=GPIO_PIN_10;            
    GPIO_Initure.Mode=GPIO_MODE_AF_PP;      
    GPIO_Initure.Pull=GPIO_PULLDOWN;        
    GPIO_Initure.Speed=GPIO_SPEED_HIGH;     
    GPIO_Initure.Alternate=GPIO_AF2_TIM5;   
    HAL_GPIO_Init(GPIOH,&GPIO_Initure);

    HAL_NVIC_SetPriority(TIM5_IRQn,1,0);    //set TIM5 interruption priority
    HAL_NVIC_EnableIRQ(TIM5_IRQn);          //open  TIM5 interruption
}

void TIM5_IRQHandler(void)//callback by startup file
{
		HAL_TIM_IRQHandler(&TIM5_Handler);	
}

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)//callback by HAL_TIM_IRQHandler
{	
	pecnt=0;
	if(echo_switch==1)
	{
		 pecnt++;
	}
}		


void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)//callback by HAL_TIM_IRQHandler
{
		if(echo_switch==1)
			{	  			
				echo_switch=2;
				
				iccnt=HAL_TIM_ReadCapturedValue(&TIM5_Handler,TIM_CHANNEL_1);
				TIM_RESET_CAPTUREPOLARITY(&TIM5_Handler,TIM_CHANNEL_1);   
				TIM_SET_CAPTUREPOLARITY(&TIM5_Handler,TIM_CHANNEL_1,TIM_ICPOLARITY_RISING);
			}
			if(echo_switch==0)
			{
				iccnt=0;
				echo_switch=1;
				
				__HAL_TIM_DISABLE(&TIM5_Handler);
				__HAL_TIM_SET_COUNTER(&TIM5_Handler,0);
				TIM_RESET_CAPTUREPOLARITY(&TIM5_Handler,TIM_CHANNEL_1);
				TIM_SET_CAPTUREPOLARITY(&TIM5_Handler,TIM_CHANNEL_1,TIM_ICPOLARITY_FALLING);
				__HAL_TIM_ENABLE(&TIM5_Handler);
			}
}

void trig_initialize(void)//initialize pin which is used as ultrasonic trigger
{
	GPIO_InitTypeDef GPIO_Initure;
	__HAL_RCC_GPIOA_CLK_ENABLE();
	
	GPIO_Initure.Pin=GPIO_PIN_7;            
	GPIO_Initure.Mode=GPIO_MODE_OUTPUT_PP;      
	GPIO_Initure.Pull=GPIO_PULLUP;        
	GPIO_Initure.Speed=GPIO_SPEED_HIGH;
  
	HAL_GPIO_Init(GPIOA,&GPIO_Initure);
}

void trig_emit(void)//emit ultrasonic wave by providing 15us high-level signal
{
		HAL_GPIO_WritePin(GPIOA,GPIO_PIN_7,GPIO_PIN_SET);
		delay_us (15);
		HAL_GPIO_WritePin(GPIOA,GPIO_PIN_7,GPIO_PIN_RESET);
}

float ultrasonic_meter(void)
{
	float temp;
	
	if(echo_switch==2)
		{
			temp=pecnt; 
			temp*=0XFFFFFFFF;
			temp+=iccnt;
			temp/=5800;
			echo_switch=0;
			return temp;
		}
		else
		{
		return 0;
		}
}

ultrasonic meter.h

C/C++
#include "sys.h"

extern TIM_HandleTypeDef TIM5_Handler;
extern long long pecnt;//TIM5 period elapse cnt
extern long long iccnt;//TIM5 input capture cnt
extern int echo_switch;


void TIM5_CH1_Cap_Init(u32 arr,u16 psc);
void trig_initialize(void);
void trig_emit(void);
float ultrasonic_meter(void);

motor control.c

C/C++
#include "MOTOR.h"


TIM_HandleTypeDef TIM3_Handler;         
TIM_OC_InitTypeDef TIM3_CH1Handler,TIM3_CH2Handler;      

void TIM3_PWM_Init(u16 arr,u16 psc)//initialize TIM3 channel 1,2 to provide PWM signal 
{ 	
		
    TIM3_Handler.Instance=TIM3;            
    TIM3_Handler.Init.Prescaler=psc;       
    TIM3_Handler.Init.CounterMode=TIM_COUNTERMODE_UP; 
    TIM3_Handler.Init.Period=arr;          
    TIM3_Handler.Init.ClockDivision=TIM_CLOCKDIVISION_DIV1;
    HAL_TIM_PWM_Init(&TIM3_Handler);     
    
    TIM3_CH1Handler.OCMode=TIM_OCMODE_PWM1;  
    TIM3_CH1Handler.Pulse=100;                                    
    TIM3_CH1Handler.OCPolarity=TIM_OCPOLARITY_HIGH;  
	
    HAL_TIM_PWM_ConfigChannel(&TIM3_Handler,&TIM3_CH1Handler,TIM_CHANNEL_1); 
    HAL_TIM_PWM_Start(&TIM3_Handler,TIM_CHANNEL_1); 
	
		TIM3_CH2Handler.OCMode=TIM_OCMODE_PWM1;  
    TIM3_CH2Handler.Pulse=100;                                    
    TIM3_CH2Handler.OCPolarity=TIM_OCPOLARITY_HIGH;
	
		HAL_TIM_PWM_ConfigChannel(&TIM3_Handler,&TIM3_CH2Handler,TIM_CHANNEL_2); 
    HAL_TIM_PWM_Start(&TIM3_Handler,TIM_CHANNEL_2); 
}

void HAL_TIM_PWM_MspInit(TIM_HandleTypeDef *htim)// enable pins used to transmit PWM signal
{
    GPIO_InitTypeDef GPIO_Initure;
		__HAL_RCC_TIM3_CLK_ENABLE();			 
    __HAL_RCC_GPIOC_CLK_ENABLE();
		__HAL_RCC_GPIOB_CLK_ENABLE();
	
    GPIO_Initure.Pin=GPIO_PIN_6|GPIO_PIN_7;           
    GPIO_Initure.Mode=GPIO_MODE_AF_PP;   
    GPIO_Initure.Pull=GPIO_PULLUP;           
    GPIO_Initure.Speed=GPIO_SPEED_HIGH;    
		GPIO_Initure.Alternate=GPIO_AF2_TIM3; 
    HAL_GPIO_Init(GPIOC,&GPIO_Initure);
	
		GPIO_Initure.Pin=GPIO_PIN_4|GPIO_PIN_5;           
    GPIO_Initure.Mode=GPIO_MODE_AF_PP;   
    GPIO_Initure.Pull=GPIO_PULLUP;           
    GPIO_Initure.Speed=GPIO_SPEED_HIGH;    
		GPIO_Initure.Alternate=GPIO_AF2_TIM3; 
    HAL_GPIO_Init(GPIOB,&GPIO_Initure);
}

void motor_initialize(void){//enable pins used to control motor direction by tranmitting level signal
		GPIO_InitTypeDef GPIO_Initure;
		__HAL_RCC_GPIOE_CLK_ENABLE();
		__HAL_RCC_GPIOI_CLK_ENABLE();
	
		GPIO_Initure.Pin=GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6;           
    GPIO_Initure.Mode=GPIO_MODE_OUTPUT_PP;   
    GPIO_Initure.Pull=GPIO_PULLUP;           
    GPIO_Initure.Speed=GPIO_SPEED_HIGH;    
		 
    HAL_GPIO_Init(GPIOE,&GPIO_Initure);
	
		GPIO_Initure.Pin=GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7;           
    GPIO_Initure.Mode=GPIO_MODE_OUTPUT_PP;   
    GPIO_Initure.Pull=GPIO_PULLUP;           
    GPIO_Initure.Speed=GPIO_SPEED_HIGH;    
		 
    HAL_GPIO_Init(GPIOI,&GPIO_Initure);
}

motor control.h

C/C++
#include "sys.h"
 
extern TIM_HandleTypeDef TIM3_Handler;       
extern TIM_OC_InitTypeDef TIM3_CH1Handler,TIM3_CH2Handler;   

void TIM3_PWM_Init(u16 arr,u16 psc);
void motor_initialize(void);

controller.c

C/C++
#include "PID.h"
#include "ULTRASONIC_METER.h"
#define deadzone 280
uint32_t duty_ratio=0;//note that this is not actual duty ratio; actual duty ratio should divide this variable by auto-reload value
float e0,e1,e_sum=0;//distance error recorder
float distance;//distance measure from ultrasonic meter

void pid_calculator(void){
	
	float kp=3300;
	float ti=2.1053;// this is actually reciprocal of ti
	float td=0.11875;
	float t=0.005;//calculate cycle duration
	float reference=0.2;//target distance 
	float e_temp;
	
	distance=ultrasonic_meter();
	e0=distance-reference;
	
if(distance!=0){//note that negative duty ratio cannnot reverse motor direction, thus it should be absolute value
	if(e0>0){
	e_temp=e0;
	e_sum+=e_temp;
	duty_ratio=kp*e_temp+ti*t*e_sum+td*(e0-e1)/t+deadzone;
	}
	
	if (e0<0){
	e_temp=e0;
	e_sum+=e_temp;
	duty_ratio=-(kp*e_temp+ti*t*e_sum+td*(e0-e1)/t)+deadzone;
	e1=e_temp;
	}
}
}

void pid_controller(void){
	
	if (e0<0){
		car_direction (1);
	}
	else {
		car_direction (-1);
	}
	car_speed();
	
}

void car_direction(int dir){
	
	switch (dir){
		
		case 1 :
		{
			HAL_GPIO_WritePin(GPIOE,GPIO_PIN_3,GPIO_PIN_SET);
			HAL_GPIO_WritePin(GPIOE,GPIO_PIN_4,GPIO_PIN_SET);
			HAL_GPIO_WritePin(GPIOI,GPIO_PIN_4,GPIO_PIN_SET);
			HAL_GPIO_WritePin(GPIOI,GPIO_PIN_5,GPIO_PIN_SET);
			
			HAL_GPIO_WritePin(GPIOE,GPIO_PIN_5,GPIO_PIN_RESET);
			HAL_GPIO_WritePin(GPIOE,GPIO_PIN_6,GPIO_PIN_RESET);
			HAL_GPIO_WritePin(GPIOI,GPIO_PIN_6,GPIO_PIN_RESET);
			HAL_GPIO_WritePin(GPIOI,GPIO_PIN_7,GPIO_PIN_RESET);
		}
		break;
		
		case -1 :
		{
			HAL_GPIO_WritePin(GPIOE,GPIO_PIN_3,GPIO_PIN_RESET);
			HAL_GPIO_WritePin(GPIOE,GPIO_PIN_4,GPIO_PIN_RESET);
			HAL_GPIO_WritePin(GPIOI,GPIO_PIN_4,GPIO_PIN_RESET);
			HAL_GPIO_WritePin(GPIOI,GPIO_PIN_5,GPIO_PIN_RESET);
			
			HAL_GPIO_WritePin(GPIOE,GPIO_PIN_5,GPIO_PIN_SET);
			HAL_GPIO_WritePin(GPIOE,GPIO_PIN_6,GPIO_PIN_SET);
			HAL_GPIO_WritePin(GPIOI,GPIO_PIN_6,GPIO_PIN_SET);
			HAL_GPIO_WritePin(GPIOI,GPIO_PIN_7,GPIO_PIN_SET);
		}
		break;

		
	}
}
	
	
void car_speed(void) {//assign value to CCR(capture compare register) to manipulate duty ratio
	
	TIM3->CCR1=duty_ratio;
	TIM3->CCR2=duty_ratio;
	
}

controller.h

C/C++
#include "sys.h"

extern uint32_t PWM;
extern float e0,e1,e2,distance;

void pid_calculator(void);
void pid_controller(void);
void car_direction(int dir);
void car_speed(void);

sys.c

C/C++
credit: http://www.alientek.com
#include "sys.h"
//this is open-source technical support from Alientek
//the main function of this file is initialize system clock and set ram address
void Cache_Enable(void)
{
    SCB_EnableICache();
    SCB_EnableDCache();
	SCB->CACR|=1<<2;   
}

void Stm32_Clock_Init(u32 plln,u32 pllm,u32 pllp,u32 pllq)
{
    HAL_StatusTypeDef ret = HAL_OK;
    RCC_OscInitTypeDef RCC_OscInitStructure; 
    RCC_ClkInitTypeDef RCC_ClkInitStructure;
	
    __HAL_RCC_PWR_CLK_ENABLE(); 
 
    __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
      
    RCC_OscInitStructure.OscillatorType=RCC_OSCILLATORTYPE_HSE;   
    RCC_OscInitStructure.HSEState=RCC_HSE_ON;                
    RCC_OscInitStructure.PLL.PLLState=RCC_PLL_ON;				
    RCC_OscInitStructure.PLL.PLLSource=RCC_PLLSOURCE_HSE;        
    RCC_OscInitStructure.PLL.PLLM=pllm;
    RCC_OscInitStructure.PLL.PLLN=plln;
    RCC_OscInitStructure.PLL.PLLP=pllp; 
    RCC_OscInitStructure.PLL.PLLQ=pllq; 
    ret=HAL_RCC_OscConfig(&RCC_OscInitStructure);
    if(ret!=HAL_OK) while(1);
    
    ret=HAL_PWREx_EnableOverDrive(); 
    if(ret!=HAL_OK) while(1);
    
    RCC_ClkInitStructure.ClockType=(RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2);
    RCC_ClkInitStructure.SYSCLKSource=RCC_SYSCLKSOURCE_PLLCLK;
    RCC_ClkInitStructure.AHBCLKDivider=RCC_SYSCLK_DIV1;
    RCC_ClkInitStructure.APB1CLKDivider=RCC_HCLK_DIV4;
    RCC_ClkInitStructure.APB2CLKDivider=RCC_HCLK_DIV2;
    
    ret=HAL_RCC_ClockConfig(&RCC_ClkInitStructure,FLASH_LATENCY_7);
    if(ret!=HAL_OK) while(1);
}


#ifdef  USE_FULL_ASSERT

void assert_failed(uint8_t* file, uint32_t line)
{ 
	while (1)
	{
	}
}
#endif


u8 Get_ICahceSta(void)
{
    u8 sta;
    sta=((SCB->CCR)>>17)&0X01;
    return sta;
}


u8 Get_DCahceSta(void)
{
    u8 sta;
    sta=((SCB->CCR)>>16)&0X01;
    return sta;
}

 
__asm void WFI_SET(void)
{
	WFI;		  
}

__asm void INTX_DISABLE(void)
{
	CPSID   I
	BX      LR	  
}

__asm void INTX_ENABLE(void)
{
	CPSIE   I
	BX      LR  
}

__asm void MSR_MSP(u32 addr) 
{
	MSR MSP, r0 		
	BX r14
}

sys.h

C/C++
credit: http://www.alientek.com
#ifndef _SYS_H
#define _SYS_H
#include "stm32f7xx.h"
#include "core_cm7.h"
#include "stm32f7xx_hal.h"
#define SYSTEM_SUPPORT_OS		 
//this is open-source technical support from Alientek
//the main function of this file is initialize system clock and set ram address
///////////////////////////////////////////////////////////////////////////////////

typedef int32_t  s32;
typedef int16_t s16;
typedef int8_t  s8;

typedef const int32_t sc32;  
typedef const int16_t sc16;  
typedef const int8_t sc8;  

typedef __IO int32_t  vs32;
typedef __IO int16_t  vs16;
typedef __IO int8_t   vs8;

typedef __I int32_t vsc32;  
typedef __I int16_t vsc16; 
typedef __I int8_t vsc8;   

typedef uint32_t  u32;
typedef uint16_t u16;
typedef uint8_t  u8;

typedef const uint32_t uc32;  
typedef const uint16_t uc16;  
typedef const uint8_t uc8; 

typedef __IO uint32_t  vu32;
typedef __IO uint16_t vu16;
typedef __IO uint8_t  vu8;

typedef __I uint32_t vuc32;  
typedef __I uint16_t vuc16; 
typedef __I uint8_t vuc8;  

#define ON	1
#define OFF	0
#define Write_Through() (*(__IO uint32_t*)0XE000EF9C=1UL<<2)  

void Cache_Enable(void);                                     
void Stm32_Clock_Init(u32 plln,u32 pllm,u32 pllp,u32 pllq);  
u8 Get_ICahceSta(void); 
u8 Get_DCahceSta(void); 
 
void WFI_SET(void);		 
void INTX_DISABLE(void); 
void INTX_ENABLE(void); 
void MSR_MSP(u32 addr); 
#endif

Credits

wzh_hackster

wzh_hackster

4 projects • 4 followers

Comments