前言:

        本篇主要讲述实现PID闭环操作之前的通过霍尔编码器计算出单个电机的转速,同时会涉及到一点编码器原理,这里我会给大家简单讲解一下。

霍尔编码器:

        这是在某宝界面上获取的编码器接线图,在开始的时候一定要确保接线是正确的,最开始我们这边的小车上就因为接线错误而导致编码器一直没有回传会值来,一直是0。

        那么,什么是编码器呢?一句话概括的话,编码器是测速的,放在电机上可以测得电机的转速。编码器可以按照输出信号分为两种编码器,增量式编码器与绝对式编码器。我们这里用的霍尔传感器呢就是一种增量式编码器,我们这里重点讲一下增量式传感器

增量式编码器是将设备运动时的位移信息变成连续的脉冲信号,脉冲个数表示位移量的大 小。其特点如下:

  • 只有当设备运动时才会输出信号。
  • 一般会输出通道A和通道B 两组信号,并且有90° 的相位差(1/4个周期),同时采集这两组信号就可以计算设备的运动速度和方向。

如下图,通道A和通道B的信号的周期相同,且相位相差1/4个周期,结合两相的信号值:

  • 当B相和A相先是都读到高电平(1 1),再B读到高电平,A读到低电平(1 0),则为顺时针转
  • 当B相和A相先是都读到低电平(0 0),再B读到高电平,A读到低电平(1 0),则为逆时针转
  • 除通道A、通道B 以外,还会设置一个额外的通道Z 信号,表示编码器特定的参考位置

        为了提高我们获取霍尔传感器传回的值的精度,我们通常会使用一种叫做编码器倍频的技术。编码器倍频是什么意思呢,比如某光栅编码器一圈有N个栅格,理论上电机带动编码器转一圈

,只能输出N个信号,通过倍频技术,可以实现转一圈,却能输出N*n个信号,这里的n为倍频数。

增量式编码器输出的脉冲波形一般为占空比50% 的方波,通道A 和B 相位差为90°。

  • 如果只使用通道A计数,并且只捕获通道A的上升沿,则一圈的计数值=码盘的栅格数,即为1倍频(没有倍频)
  • 如果只使用通道A计数,并且捕获了通道A的上升沿和下降沿,则编码器转一圈的计数值翻倍,实现2倍频
  • 如果既使用通道A计数,又使用通道B计数,且都捕获了上升沿和下降沿,则实现了4倍频。也就是使用TIM_EncoderMode_TI12,这会在通道A的上升沿和下降沿和通道B的上升沿和下降沿都进行一次采集。

 配置定时器的输入捕获模式:

        我们大致讲完了编码器的有关知识,那么我们如何利用定时器的输入捕获模式呢。这里我以TIM4为例,使用TIM4的CH1(PB6)和TIM4的CH2(PB7)分别连接编码器的B相和A相

        首先开启GPIO口和对应定时器的时钟

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4,ENABLE);

       配置对应管脚为浮空输入

GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7|GPIO_Pin_6;
GPIO_Init(GPIOB, &GPIO_InitStructure);//PB7

   配置时基单元

TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; 
 
TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
TIM_TimeBaseStructure.TIM_Prescaler = 0x0;
TIM_TimeBaseStructure.TIM_Period = 65535; 
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);

   配置捕获的一些参数

TIM_ICInitTypeDef TIM_ICInitStructure;
 
TIM_ICStructInit(&TIM_ICInitStructure); //把TIM_ICInitStruct 中的每一个参数按缺省值填入
TIM_ICInitStructure.TIM_ICFilter = 10;  //设置滤波器长度
TIM_ICInit(TIM4, &TIM_ICInitStructure); 

        同时,千万不要忘记把定时器工作模式设定为输入捕获模式,同时,我们这里使用的是TIM_EncoderMode_TI12,正好对应了我们上面将的4倍频

TIM_EncoderInterfaceConfig(TIM4, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);//使用编码器模式3

        接下来要做的就是设置初始值,使能定时器和定时器中断

TIM_ClearFlag(TIM4, TIM_FLAG_Update);//
TIM_ITConfig(TIM4, TIM_IT_Update, ENABLE);
TIM_SetCounter(TIM4,0);
TIM_Cmd(TIM4, ENABLE); 

那么问题来了,如何去计算出速度呢?

        请教了智然学长后,我决定使用rad/s来表示速度,我的思路是利用滴答定时器来定一个5秒的时,然后我们在这5秒内用手转动轮胎一圈,让串口将轮胎转动一圈中计数器所记录下的脉冲值给发送到串口助手。多次测量取平均值,这样我们就能计算出每转动一圈,编码器所传输的脉冲来了。之后更改滴答定时器定时1秒,每隔一秒将这一秒内编码器所发出的脉冲读取出来,并将定时器的CNT寄存器清零。一秒内的脉冲再除以转动一圈的脉冲,就可以计算出一秒的时间内轮胎转了多少圈

代码部分:

encoder.c

#include "encoder.h"
#include "stm32f10x.h"
 
unsigned char Encoder_flag;//ÓÃÀ´ÔڵδðÀï½øÈëÖжÏ
unsigned int Motor1_r;
 
//Encoder2_A		->		PB5		->		TIM3_CH2(Remap)
//Encoder2_B		->		PB4		->		TIM3_CH1(Remap)
//Encoder3_A		->		PB3		->		TIM2_CH2(Remap)
//Encoder3_B		->		PA15	->		TIM2_CH1(Remap)
//Encoder4_A		->		PA0		->		TIM5_CH1
//Encoder4_B		->		PA1		->		TIM5_CH2
 
void Encoder1_Init_TIM4()
{
	//Encoder1_A		->		PB7		->		TIM4_CH2
	//Encoder1_B		->		PB6		->		TIM4_CH1
	TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; 
	TIM_ICInitTypeDef TIM_ICInitStructure;  
	GPIO_InitTypeDef GPIO_InitStructure;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4,ENABLE);//¿ª¶¨Ê±Æ÷4µÄʱÖÓ
	
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
	GPIO_Init(GPIOB, &GPIO_InitStructure);//PB7
	
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
	GPIO_Init(GPIOB, &GPIO_InitStructure);//PB6
	
	TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
	TIM_TimeBaseStructure.TIM_Prescaler = 0x0; 
	TIM_TimeBaseStructure.TIM_Period = 65535; 
	TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
	TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);  
	
	TIM_EncoderInterfaceConfig(TIM4, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);//???????3
	//²ÉÓÃTIM_EncoderMode_TI12£¬CH1ºÍCH2µÄÉÏϱßÑض¼²É¼¯
	TIM_ICStructInit(&TIM_ICInitStructure); //?TIM_ICInitStruct ?????????????
	TIM_ICInitStructure.TIM_ICFilter = 10;  //???????
	TIM_ICInit(TIM4, &TIM_ICInitStructure);//?? TIM_ICInitStruct ????????	TIMx
 
	TIM_ClearFlag(TIM4, TIM_FLAG_Update);//
	TIM_ITConfig(TIM4, TIM_IT_Update, ENABLE);//???????
	
	TIM_SetCounter(TIM4,0);
	TIM_Cmd(TIM4, ENABLE); 
	Encoder_flag = 1;//·½±ãÔڵδðÀïÃæ¼ÆËã
}
	
float Read_Encoder1(void)
{
	int Encoder_TIM = 0;  //Æäʵ¾ÍÊÇȦÊý
//	float Speed = 0.0;  
	Encoder_TIM= (short)TIM4 -> CNT;   
	TIM4 -> CNT=0;
	return Encoder_TIM;
}
 
void TIM4_IRQHandler(void)
{
	if(TIM_GetITStatus(TIM4,TIM_IT_Update)!=RESET) 
	{	
		TIM_ClearITPendingBit(TIM4,TIM_IT_Update);
	}		 	
}
 

encoder.h

#ifndef __ENCODER_H
#define __ENCODER_H
 
void Encoder1_Init_TIM4(void);
float Read_Encoder1(void);
void TIM4_IRQHandler(void);
 
 
#endif

现阶段的sysclock.c

#include "stm32f10x.h"
#include "sysclock.h"
#include "encoder.h"
#include "stdio.h"	//ΪÁËʹÓÃprintf
 
unsigned int time_delay; //¶¨ÒåΪȫ¾Ö±äÁ¿
unsigned int led_count;
unsigned int encoder_count;//ÓÃÀ´¼ÆÊý
unsigned int encoder_media;//ÓÃÀ´´«µÝȦÊýµÄÖµ
extern unsigned char led_flag;
extern unsigned char Encoder_flag;
extern unsigned int Motor1_r;
/*
	SystemCoreClock / 1000  	1msÖжÏÒ»´Î
	SystemCoreClock / 1000000 1usÖжÏÒ»´Î
*/
 
 
 
void delay_ms(unsigned int time_ms)
{
	if (SysTick_Config(SystemCoreClock/1000))
	{
		while (1);
	}
	time_delay=time_ms;
	while(time_delay);
	SysTick->CTRL=0x00; 
	SysTick->VAL =0X00; 
}
 
void delay_us(unsigned int time_us)
{
  if (SysTick_Config(SystemCoreClock/1000000))
  {
     while (1);
  }
	time_delay=time_us;
	while(time_delay);
	SysTick->CTRL=0x00; 
	SysTick->VAL =0X00; 
}
 
void SysTick_Handler(void)//ÔÚLEDÀÿ10ms½øÈëÒ»´ÎÖжÏ
{
	if(time_delay)
	{
		time_delay--;
	}
	if(led_flag == 1)
	{
		led_count++;
		if(led_count % (1<<7) == 0)
		GPIO_WriteBit(GPIOC, GPIO_Pin_13, (BitAction)(!GPIO_ReadOutputDataBit(GPIOC, GPIO_Pin_13)));
	}
	if(Encoder_flag == 1)
	{
		if(++encoder_count == 100)
		{
			encoder_count = 0;
			encoder_media = Read_Encoder1();
			Motor1_r = encoder_media/900;//¼ÆËãËٶȣ¬µ¥Î»ÊÇrad/s
			printf("%d\r\n",Motor1_r);
		}
	}
}

特别鸣谢:

        博客借鉴于编码器计数原理与电机测速原理——多图解析 - 知乎 (zhihu.com)

最终编码器代码:

        encoder.c 

#include "encoder.h"
#include "stm32f10x.h"
 
unsigned char Encoder_flag;//ÓÃÀ´ÔڵδðÀï½øÈëÖжÏ
unsigned int Motor1_r;
unsigned int Motor2_r;
unsigned int Motor3_r;
unsigned int Motor4_r;
 
void Encoder1_Init_TIM4()
{
	//Encoder1_A		->		PB7		->		TIM4_CH2
	//Encoder1_B		->		PB6		->		TIM4_CH1
	TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; 
	TIM_ICInitTypeDef TIM_ICInitStructure;  
	GPIO_InitTypeDef GPIO_InitStructure;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4,ENABLE);//¿ª¶¨Ê±Æ÷4µÄʱÖÓ
	
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
	GPIO_Init(GPIOB, &GPIO_InitStructure);//PB7
	
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
	GPIO_Init(GPIOB, &GPIO_InitStructure);//PB6
	
	TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
	TIM_TimeBaseStructure.TIM_Prescaler = 0x0; 
	TIM_TimeBaseStructure.TIM_Period = 65535; 
	TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
	TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);  
	
	TIM_EncoderInterfaceConfig(TIM4, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);
	
	TIM_ICStructInit(&TIM_ICInitStructure); 
	TIM_ICInitStructure.TIM_ICFilter = 10;  
	TIM_ICInit(TIM4, &TIM_ICInitStructure);
 
	TIM_ClearFlag(TIM4, TIM_FLAG_Update);//
	TIM_ITConfig(TIM4, TIM_IT_Update, ENABLE);
	
	TIM_SetCounter(TIM4,0);
	TIM_Cmd(TIM4, ENABLE); 
	Encoder_flag = 1;
}
 
void Encoder2_Init_TIM3()
{
	//Encoder2_A		->		PB5		->		TIM3_CH2(Remap)
	//Encoder2_B		->		PB4		->		TIM3_CH1(Remap)
	TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; 
	TIM_ICInitTypeDef TIM_ICInitStructure;  
	GPIO_InitTypeDef GPIO_InitStructure;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);	
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
	
	GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3 ,ENABLE );                 
 
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
	GPIO_Init(GPIOB, &GPIO_InitStructure);
	
	TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
	TIM_TimeBaseStructure.TIM_Period = 65535;
	TIM_TimeBaseStructure.TIM_Prescaler = 0x0;
	TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); 
	
	TIM_EncoderInterfaceConfig(TIM3, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);
	TIM_ICStructInit(&TIM_ICInitStructure); 
	TIM_ICInitStructure.TIM_ICFilter = 10;  
	TIM_ICInit(TIM3, &TIM_ICInitStructure);
 
	TIM_ClearFlag(TIM3, TIM_FLAG_Update);
	TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE);
	
	TIM_SetCounter(TIM3,0);
	TIM_Cmd(TIM3, ENABLE);
	
}
 
void Encoder3_Init_TIM2(void)
{
	//Encoder3_A		->		PB3		->		TIM2_CH2(Remap)
	//Encoder3_B		->		PA15	->		TIM2_CH1(Remap)
	TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; 
	TIM_ICInitTypeDef TIM_ICInitStructure;  
	GPIO_InitTypeDef GPIO_InitStructure;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOA,ENABLE);	
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
	GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE);
	GPIO_PinRemapConfig(GPIO_PartialRemap1_TIM2 ,ENABLE );                 
 
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
	GPIO_Init(GPIOB, &GPIO_InitStructure);//PB3
	
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
	GPIO_Init(GPIOA, &GPIO_InitStructure);//PA15
	
	TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
	TIM_TimeBaseStructure.TIM_Period = 65535;
	TIM_TimeBaseStructure.TIM_Prescaler = 0x0;
	TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); 
	
	TIM_EncoderInterfaceConfig(TIM2, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);
	TIM_ICStructInit(&TIM_ICInitStructure); 
	TIM_ICInitStructure.TIM_ICFilter = 10;  
	TIM_ICInit(TIM2, &TIM_ICInitStructure);
 
	TIM_ClearFlag(TIM2, TIM_FLAG_Update);
	TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
	
	TIM_SetCounter(TIM2,0);
	TIM_Cmd(TIM2, ENABLE);
}
 
void Encoder4_Init_TIM5()
{
	//Encoder4_A		->		PA0		->		TIM5_CH1
	//Encoder4_B		->		PA1		->		TIM5_CH2
	TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; 
	TIM_ICInitTypeDef TIM_ICInitStructure;  
	GPIO_InitTypeDef GPIO_InitStructure;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5,ENABLE);
	
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	
	TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
	TIM_TimeBaseStructure.TIM_Prescaler = 0x0; 
	TIM_TimeBaseStructure.TIM_Period = 65535; 
	TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
	TIM_TimeBaseInit(TIM5, &TIM_TimeBaseStructure);  
	
	TIM_EncoderInterfaceConfig(TIM5, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);
 
	TIM_ICStructInit(&TIM_ICInitStructure); 
	TIM_ICInitStructure.TIM_ICFilter = 10; 
	TIM_ICInit(TIM5, &TIM_ICInitStructure);
 
	TIM_ClearFlag(TIM5, TIM_FLAG_Update);
	TIM_ITConfig(TIM5, TIM_IT_Update, ENABLE);
	
	TIM_SetCounter(TIM5,0);
	TIM_Cmd(TIM5, ENABLE); 
}
 
float Read_Encoder1(void)//TIM4
{
	int Encoder1_TIM = 0; 
	Encoder1_TIM = (short)TIM4 -> CNT;  
	TIM4 -> CNT=0;
	return Encoder1_TIM;
}
float Read_Encoder2(void)//TIM3
{
	int Encoder2_TIM = 0; 
	Encoder2_TIM = (short)TIM3 -> CNT;  
	TIM3 -> CNT=0;
	return Encoder2_TIM;
}
float Read_Encoder3(void)//TIM2
{
	int Encoder3_TIM = 0; 
	Encoder3_TIM = (short)TIM2 -> CNT;  
	TIM2 -> CNT=0;
	return Encoder3_TIM;
}
float Read_Encoder4(void)//TIM5
{
	int Encoder4_TIM = 0; 
	Encoder4_TIM = (short)TIM5 -> CNT;  
	TIM5 -> CNT=0;
	return Encoder4_TIM;
}
void TIM4_IRQHandler(void)
{
	if(TIM_GetITStatus(TIM4,TIM_IT_Update)!=RESET) 
	{	
		TIM_ClearITPendingBit(TIM4,TIM_IT_Update);
	}		 	
}
 
void TIM3_IRQHandler(void)
{
	if(TIM_GetITStatus(TIM3,TIM_IT_Update)!=RESET) 
	{	
		TIM_ClearITPendingBit(TIM3,TIM_IT_Update);
	}		 	
}
 
void TIM2_IRQHandler(void)
{
	if(TIM_GetITStatus(TIM2,TIM_IT_Update)!=RESET) 
	{	
		TIM_ClearITPendingBit(TIM2,TIM_IT_Update);
	}		 	
}
 
void TIM5_IRQHandler(void)
{
	if(TIM_GetITStatus(TIM5,TIM_IT_Update)!=RESET) 
	{	
		TIM_ClearITPendingBit(TIM5,TIM_IT_Update);
	}		 	
}

encoder.h

#ifndef __ENCODER_H
#define __ENCODER_H
 
void Encoder1_Init_TIM4(void);
void Encoder2_Init_TIM3(void);
void Encoder3_Init_TIM2(void);
void Encoder4_Init_TIM5(void);
 
float Read_Encoder1(void);
float Read_Encoder2(void);
float Read_Encoder3(void);
float Read_Encoder4(void);
 
 
void TIM4_IRQHandler(void);
void TIM3_IRQHandler(void);
void TIM2_IRQHandler(void);
void TIM5_IRQHandler(void);
 
#endif

main.c

#include "stm32f10x.h"
#include "led.h"
#include "sysclock.h"
#include "motor.h"
#include "UART.h"
#include "encoder.h"
 
 
int main()
{
	LED_init();
	Motor1_Init();
	Motor2_Init();
	Motor3_Init();
	Motor4_Init();
	USART2_Init(115200);
	Encoder1_Init_TIM4();
	Encoder2_Init_TIM3();
	Encoder3_Init_TIM2();
	Encoder4_Init_TIM5();
	GPIO_WriteBit(GPIOC, GPIO_Pin_12, Bit_RESET);
	USART_SendString(USART2,"hello\r\n");
	while(1)
	{
//		Motor1_forward(1999);
//		Motor2_forward(7999);
//		Motor3_forward(1999);
//		Motor4_forward(1999);
		data_processing();
	}
}

sysclock.c

#include "stm32f10x.h"
#include "sysclock.h"
#include "encoder.h"
#include "stdio.h"	
 
unsigned int time_delay; 
unsigned int led_count;
unsigned int encoder_count;
unsigned int encoder_media_1;
unsigned int encoder_media_2;
unsigned int encoder_media_3;
unsigned int encoder_media_4;
extern unsigned char led_flag;
extern unsigned char Encoder_flag;
extern unsigned int Motor1_r;
extern unsigned int Motor2_r;
extern unsigned int Motor3_r;
extern unsigned int Motor4_r;
 
 
 
void delay_ms(unsigned int time_ms)
{
	if (SysTick_Config(SystemCoreClock/1000))
	{
		while (1);
	}
	time_delay=time_ms;
	while(time_delay);
	SysTick->CTRL=0x00; 
	SysTick->VAL =0X00; 
}
 
void delay_us(unsigned int time_us)
{
  if (SysTick_Config(SystemCoreClock/1000000))
  {
     while (1);
  }
	time_delay=time_us;
	while(time_delay);
	SysTick->CTRL=0x00; 
	SysTick->VAL =0X00; 
}
 
void SysTick_Handler(void)
{
	if(time_delay)
	{
		time_delay--;
	}
	if(led_flag == 1)
	{
		led_count++;
		if(led_count % (1<<7) == 0)
		GPIO_WriteBit(GPIOC, GPIO_Pin_13, (BitAction)(!GPIO_ReadOutputDataBit(GPIOC, GPIO_Pin_13)));
	}
	if(Encoder_flag == 1)
	{
		if(++encoder_count == 100)
		{
			encoder_count = 0;
			encoder_media_1 = Read_Encoder1();
			encoder_media_2 = Read_Encoder2();
			encoder_media_3 = Read_Encoder3();
			encoder_media_4 = Read_Encoder4();
			Motor1_r = encoder_media_1/900;
			Motor2_r = encoder_media_2/900;
			Motor3_r = encoder_media_3/900;
			Motor4_r = encoder_media_4/900;
			printf("Motor1 = %d\r\n",Motor1_r);
			printf("Motor2 = %d\r\n",Motor2_r);
			printf("Motor3 = %d\r\n",Motor3_r);
			printf("Motor4 = %d\r\n",Motor4_r);
		}
	}
}