Tuần 1 : Lý thuyết

Posted on

Tuần 1 : Lý thuyết.

Advertisements

Tuần 1 : Lý thuyết

Posted on Updated on

Tuần 1 : Lý thuyết.

Tuần 1 : Lý thuyết

Posted on Updated on

Bài 1 : Code PWM + Read Encoder :v
Công cụ : Keil ARM 4.72a
Chip : 103RDT6
Debug : RS232
——————————————-

+ encoder chỉ đọc được trên hai kênh TIMX_CH1 và TIMX_CH2 của tất cả các kênh timer (1,2,3,4,8)
+trên STM32 hỗ trợ đọc encoder ở ba chế độ 1X, 2X và 4X. Nhưng chắc ở đây bác nào cũng thích 4X nên mình chỉ nói về 4X, đã dùng 4X thì phải dùng đến 74HC14 để làm vuông xung đầu vào, ko thì STM32 sẽ ko đọc được
@Chú Hiền, phải đưa hai kênh A, B vào CH1 và CH2 của timer_2, hàm đã hỗ trợ chức năng xác định chiều quay. Ví dụ khi quay thuận thì đọc được giá trị xung là dương, khi quay ngược đọc được giá trị xung là âm

</pre>
@<a class="profileLink" href="https://www.facebook.com/danghien719" data-hovercard="/ajax/hovercard/user.php?id=100003283994204&extragetparams=%7B%22directed_target_id%22%3A190592327771947%7D">Chú Hiền</a>, sau đây sẽ dùng timer_2 để đọc encoder
# cấu hình GPIO
void GPIO_Configuration(void)
{
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1;<span class="text_exposed_show">
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU ;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
# cấu hình timer_2 chế độ đọc 4X
void TIM2_EXTI(void)// ham khoi tao doc encoder
{
TIM2->CCMR1 = TIM_CCMR1_CC1S_0 | TIM_CCMR1_CC2S_0;
TIM2->CCER = TIM_CCER_CC1P|TIM_CCER_CC2P;
TIM2->SMCR = TIM_SMCR_SMS_0|TIM_SMCR_SMS_1;
TIM2->ARR = 65535;
TIM2->CNT = 32000;
TIM2->CR1 = TIM_CR1_CEN;
}
# cấu hình ngắt timer_3 để đọc encoder
void NVIC_Configuration(void)
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);</span>
<div class="text_exposed_show">

NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
# hàm ngắt timer_3 trong 10ms để đọc encoder
void TIM3_EXTI(void)
{

TIM_TimeBaseStructure.TIM_Period = 3599;
TIM_TimeBaseStructure.TIM_Prescaler = 99;
TIM_TimeBaseStructure.TIM_ClockDivision = 0x0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);

TIM_ARRPreloadConfig(TIM3,ENABLE);

TIM_UpdateRequestConfig(TIM3,TIM_UpdateSource_Regular);

TIM_ClearFlag(TIM3, TIM_FLAG_Update);
TIM_Cmd(TIM3, ENABLE);

TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE);

}
# khi xảy ra ngắt timer_3 thì thực hiện đọc encoder
void TIM3_IRQHandler(void)// ham doc xung encoder trong 10ms
{

if (TIM_GetITStatus(TIM3, TIM_IT_Update)==SET)
{
TIM_ClearITPendingBit(TIM3, TIM_IT_Update);
b=TIM_GetCounter(TIM2)-32000;// doc xung encoder sau thoi gian lay mau

c=b+c;// cong don xung encoder sau thoi gian lay mâu= tông xung encoder dem duoc
TIM2->CNT=32000;// het thoi gian lay mau reset lai thanh ghi TIM2=32000, doc encoder lai tu dau
}
}

# hàm chính in kết quả ra xem thế nào
int main(void)
{
RCC_Configuration();
NVIC_Configuration();
GPIO_Configuration();
USART_Configuration();
TIMER4_Configuation();
TIM2_EXTI();
TIM3_EXTI();
TIM3_IRQHandler();
while (1)
{
printf("c:%d- b:%d\n\r ",(uint32_t)c,b );
}
}

</div>
<pre>

Code NgKhôi đã dùng trên codientu.org


/* Includes ------------------------------------------------------------------*/
#include "stm32f10x.h"
#include <stdio.h>
#include <math.h>
#include "stm32f10x_it.h"

__IO int32_t encod = 0, i=0;
__IO int32_t a= 0,b=0,c=0,d=0;
__IO uint16_t pwm=0 ;
__IO uint16_t setpoin =15;
__IO double_t output=0,kp=80, ki=20,kd=1,pv=0, error=0,old_err=0, errsum=0, derr=0,sampling_time= 0.01, inv_sampling_time=100;
#ifdef __GNUC__

#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif /* __GNUC__ */
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
TIM_ICInitTypeDef TIM_ICInitStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
NVIC_InitTypeDef NVIC_InitStructure;

&nbsp;

void RCC_Configuration(void);
void GPIO_Configuration(void);
void NVIC_Configuration(void);
void USART_Configuration(void);
void TIMER4_Configuation(void);
void TIM3_EXTI(void);
void TIM3_IRQHandler(void);
void TIM2_EXTI(void);
void TIM2_IRQHandler(void);
void TIMER4_PWM(__IO uint16_t pwm);
void cal_pid (__IO uint16_t setpoin);
//uint32_t Enc_GetCount(void);
void Delay(__IO uint32_t num)
{
__IO uint32_t index = 0;

for(index = (720000 * num); index != 0; index--)
{
}
}
int main(void)
{
RCC_Configuration();
NVIC_Configuration();
GPIO_Configuration();
USART_Configuration();
TIMER4_Configuation();
GPIO_SetBits(GPIOB, GPIO_Pin_11);
TIM2_EXTI();
TIM3_EXTI();
TIM3_IRQHandler();
while (1)
{
printf("setpoin:%f- pv:%f\n\r ",(double_t)setpoin,pv );
}
}

PUTCHAR_PROTOTYPE
{

USART_SendData(USART1, (uint32_t) ch);

while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET)
{}

return ch;
}
void RCC_Configuration(void)
{
/* TIM2 clock enable */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2|RCC_APB1Periph_TIM3|RCC_APB1Periph_TIM4, ENABLE);
/* GPIOA and GPIOB clock enable */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_USART1 | RCC_APB2Periph_AFIO, ENABLE);
/* PCLK1 = HCLK/4 => 72MHz/16 = 18MHz */ //suy ra timer cua APB hoa dong 36Mhz xem trong file excel
RCC_PCLK1Config(RCC_HCLK_Div4);//
}
void GPIO_Configuration(void)
{

/* TIM2 channel 2 pin (PA.01) configuration */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU ;//GPIO_Mode_IPU//GPIO_Mode_IN_FLOATING
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9|GPIO_Pin_10|GPIO_Pin_11;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
}

&nbsp;

void NVIC_Configuration(void)
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);

NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}

void USART_Configuration(void)
{
/* Configure PA9 for USART Tx as alternate function push-pull */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* Configure PA10 for USART Rx as input floating */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* usart configuration */
USART_InitStructure.USART_BaudRate = 115200;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
/* USART configuration */
USART_Init(USART1, &USART_InitStructure);
/* Enable USART */
USART_Cmd(USART1, ENABLE);
}
void TIMER4_Configuation(void)
{

TIM_TimeBaseStructure.TIM_Prescaler = 3;// tan so xung 3kHz
TIM_TimeBaseStructure.TIM_Period = 2999;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);
TIM_Cmd(TIM4, ENABLE);
}
void TIMER4_PWM(__IO uint16_t pwm)
{
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = pwm;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OC3Init(TIM4, &TIM_OCInitStructure);
TIM_OC3PreloadConfig(TIM4, TIM_OCPreload_Enable);
TIM_ARRPreloadConfig(TIM4, ENABLE);
}
// kp=10, ki=1,kd=1,pv=0, error=0,old_err=0, errsum=0, derr=0,sampling_time= 0.01, inv_sampling_time=100;
void cal_pid (__IO uint16_t setpoin)
{
error = setpoin - pv;
errsum += error*sampling_time;
derr = (error - old_err)*inv_sampling_time;
output += ceil(kp*error+ki*errsum+kd*derr);
if (output>2980)
{
output=2980;
}
else if (output<-2980)
{
output=-2980;
}
if (output>=0)
{
pwm=output;
TIMER4_PWM(pwm);
GPIO_SetBits(GPIOB, GPIO_Pin_11);
}
else if (output<0)
{
pwm=fabs(output);
TIMER4_PWM(pwm);
GPIO_ResetBits(GPIOB, GPIO_Pin_11);
}

old_err = error;
}
void TIM2_EXTI(void)// ham khoi tao doc encoder
{
TIM_DeInit(TIM2);
TIM_TimeBaseStructure.TIM_Prescaler=1;
TIM_TimeBaseStructure.TIM_Period=65535;
TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;//TIM_CKD_DIV1
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);

TIM_ICInitStructure.TIM_Channel=TIM_Channel_1|TIM_Channel_2;
//TIM_ICInitStructure.TIM_ICPolarity= TIM_ICPolarity_BothEdge ;//TIM_ICPolarity_Falling
TIM_ICInitStructure.TIM_ICFilter=0;
TIM_ICInitStructure.TIM_ICSelection=TIM_ICSelection_DirectTI;
TIM_ICInit(TIM2, &TIM_ICInitStructure);
TIM_EncoderInterfaceConfig(TIM2, TIM_EncoderMode_TI2, TIM_ICPolarity_Falling , TIM_ICPolarity_Falling );
TIM2->CNT = 32000;
//TIM2->CNT = 0;
TIM_Cmd(TIM2,ENABLE);
//TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
// TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
}
void TIM3_EXTI(void)// NGAT TIMER3 TRONG 10MS ÐÊ ÐÊM ENCODER
{
TIM_TimeBaseStructure.TIM_Prescaler = 99; //
TIM_TimeBaseStructure.TIM_Period = 3599; // delay 10ms
TIM_TimeBaseStructure.TIM_ClockDivision = 0x0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);

TIM_ARRPreloadConfig(TIM3,ENABLE);
//TIM_PrescalerConfig(TIM3, (36000 - 1), TIM_PSCReloadMode_Immediate);
TIM_UpdateRequestConfig(TIM3,TIM_UpdateSource_Regular);

TIM_ClearFlag(TIM3, TIM_FLAG_Update);
TIM_Cmd(TIM3, ENABLE);

TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE);

}

/*void TIM2_IRQHandler(void)
{
//a=TIM_GetCounter(TIM2);
if (TIM_GetITStatus(TIM2, TIM_IT_Update)!=RESET)
{
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
a=TIM_GetCounter(TIM2);
if (a==0) {i++;}
else if (a==65535) {i--;}
//encod=i*65535+a;
//printf("xung:%d- tang:%d\n\r ",(uint32_t) encod,i );
}

}*/
void TIM3_IRQHandler(void)// ham doc xung encoder trong 10ms
{
if (TIM_GetITStatus(TIM3, TIM_IT_Update)==SET)
{
TIM_ClearITPendingBit(TIM3, TIM_IT_Update);
a=TIM_GetCounter(TIM2)-32000;// doc xung encoder sau thoi gian lay mau

b=a+b;// cong don xung encoder sau thoi gian lay mâu= tông xung encoder dem duoc
if(a>0)
{
GPIO_SetBits(GPIOB, GPIO_Pin_9);
GPIO_ResetBits(GPIOB, GPIO_Pin_10);
}
else if(a==0)
{
GPIO_SetBits(GPIOB, GPIO_Pin_9);
GPIO_SetBits(GPIOB, GPIO_Pin_10);
}
else if(a<0)
{
GPIO_ResetBits(GPIOB, GPIO_Pin_9);
GPIO_SetBits(GPIOB, GPIO_Pin_10);
}
c=fabs(a);
pv= c/2; //vân tôc dat duoc/1s
cal_pid (setpoin);
TIM2->CNT=32000;// het thoi gian lay mau reset lai thanh ghi TIM2=0, doc encoder lai tu dau
}
}

&nbsp;
#ifdef USE_FULL_ASSERT

/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t* file, uint32_t line)
{
/* User can add his own implementation to report the file name and line number,
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */

while (1)
{}
}

#endif

/**
* @}
*/

/**
* @}
*/

/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****