{"id":392,"date":"2013-02-13T19:14:02","date_gmt":"2013-02-14T03:14:02","guid":{"rendered":"http:\/\/micromouseusa.com\/?p=392"},"modified":"2017-02-11T18:24:41","modified_gmt":"2017-02-12T02:24:41","slug":"get-native-32bit-resolution-for-your-encoder-on-stm32f4","status":"publish","type":"post","link":"http:\/\/micromouseusa.com\/?p=392","title":{"rendered":"Get Native 32Bit resolution for your encoder on STM32F4"},"content":{"rendered":"<p>For those who use STM32 F10x as the MCU for Micromouse must remember all general purpose timers are 16bits that gave you 65535 max resolution. Since the mouse with fauhalber motor generate about 20000 encoder counts per cell distance traverse, we must keep track of the encoder counts to prevent overflow. Even though there were several methods to expand encoder resolution softwarely or hardwarely to 32bit, neither are preferred for this application.<\/p>\n<p>STM32F4 Series now have two 32bit general purpose timers: TIM2 and TIM5. Since the register capacity is now 32bit instead of 16bit for these 2 timers, the TIM2-&gt;CNT and TIM5-&gt;CNT registers can go beyond 65535(16bit) during in my test(obviously). If you decide to design a new mouse with stm32F4, having the 2 encoders connected to TIM2 and TIM5 will be a more no brainer choice to make your life my easier.<\/p>\n<p>The configuration code for encoder are very much likely same to STM32F10x, here is the code for setting TIM2 to quadrature encoder mode on STM32F4:<\/p>\n<p><span style=\"color: #ff6600;\">void Encoder_Configration(void)<\/span><\/p>\n<p><span style=\"color: #ff6600;\">{<\/span><\/p>\n<p><span style=\"color: #ff6600;\">\u00a0\u00a0\u00a0 NVIC_InitTypeDef NVIC_InitStructure;<\/span><\/p>\n<p><span style=\"color: #ff6600;\">\u00a0 \u00a0 GPIO_InitTypeDef GPIO_InitStructure;<\/span><\/p>\n<p><span style=\"color: #ff6600;\">\u00a0\u00a0 TIM_TimeBaseInitTypeDef\u00a0 TIM_TimeBaseStructure;<br \/>\n<\/span><\/p>\n<p><span style=\"color: #ff6600;\">\u00a0\u00a0 TIM_ICInitTypeDef TIM_ICInitStructure;<\/span><\/p>\n<p><span style=\"color: #ff6600;\">\u00a0\u00a0 \/*TIM2 clock source enable *\/<\/span><\/p>\n<p><span style=\"color: #ff6600;\">\u00a0\u00a0 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);<\/span><\/p>\n<p><span style=\"color: #ff6600;\">\u00a0\u00a0 \/* Enable GPIOA, clock *\/<\/span><\/p>\n<p><span style=\"color: #ff6600;\">\u00a0\u00a0 RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);\u00a0\u00a0\u00a0<\/span><\/p>\n<p><span style=\"color: #ff6600;\">\u00a0\u00a0 \/* Encoder unit connected to TIM2, quadrature mode *\/ \u00a0\u00a0<\/span><\/p>\n<p><span style=\"color: #ff6600;\">\u00a0 \/\/GPIOA Config\u00a0\u00a0<\/span><\/p>\n<p><span style=\"color: #ff6600;\">\u00a0\u00a0\u00a0 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;<\/span><\/p>\n<p><span style=\"color: #ff6600;\">\u00a0\u00a0\u00a0 GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;<\/span><\/p>\n<p><span style=\"color: #ff6600;\">\u00a0\u00a0\u00a0 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1;<\/span><\/p>\n<p><span style=\"color: #ff6600;\">\u00a0\u00a0\u00a0 GPIO_Init(GPIOA, &amp;GPIO_InitStructure);<\/span><\/p>\n<p><span style=\"color: #ff6600;\">\u00a0<\/span><\/p>\n<p><span style=\"color: #ff6600;\">\u00a0\u00a0\u00a0 \/* Enable the TIM2 Update Interrupt for left encoder*\/\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><\/p>\n<p><span style=\"color: #ff6600;\">\u00a0\u00a0\u00a0 NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><\/p>\n<p><span style=\"color: #ff6600;\">\u00a0\u00a0\u00a0 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 6;<\/span><\/p>\n<p><span style=\"color: #ff6600;\">\u00a0\u00a0\u00a0 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;<\/span><\/p>\n<p><span style=\"color: #ff6600;\">\u00a0\u00a0\u00a0 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;<\/span><\/p>\n<p><span style=\"color: #ff6600;\">\u00a0\u00a0\u00a0 NVIC_Init(&amp;NVIC_InitStructure);<\/span><\/p>\n<p><span style=\"color: #ff6600;\">\u00a0<\/span><\/p>\n<p><span style=\"color: #ff6600;\">\u00a0<\/span><\/p>\n<p><span style=\"color: #ff6600;\">\u00a0\u00a0\u00a0 \/* Timer configuration in Encoder mode for left encoder*\/<\/span><\/p>\n<p><span style=\"color: #ff6600;\">\u00a0\u00a0\u00a0 TIM_TimeBaseStructure.TIM_Prescaler = 0x00;\u00a0 \/\/ No prescaling<\/span><\/p>\n<p><span style=\"color: #ff6600;\">\u00a0\u00a0\u00a0 TIM_TimeBaseStructure.TIM_Period = 0xffffffff; \/\/max resolution<\/span><\/p>\n<p><span style=\"color: #ff6600;\">\u00a0\u00a0\u00a0 TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;\/\/devide by clock by one<\/span><\/p>\n<p><span style=\"color: #ff6600;\">\u00a0\u00a0\u00a0 TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;\/\/ count up\u00a0\u00a0<\/span><\/p>\n<p><span style=\"color: #ff6600;\">\u00a0\u00a0\u00a0 TIM_TimeBaseInit(TIM2, &amp;TIM_TimeBaseStructure);<\/span><\/p>\n<p><span style=\"color: #ff6600;\">\u00a0<\/span><\/p>\n<p><span style=\"color: #ff6600;\">\u00a0\u00a0\u00a0 TIM_EncoderInterfaceConfig(TIM2, TIM_EncoderMode_TI12,\u00a0 TIM_ICPolarity_Falling, TIM_ICPolarity_Falling);<\/span><\/p>\n<p><span style=\"color: #ff6600;\">\u00a0\u00a0\u00a0 TIM_ICStructInit(&amp;TIM_ICInitStructure);<\/span><\/p>\n<p><span style=\"color: #ff6600;\">\u00a0\u00a0\u00a0 TIM_ICInitStructure.TIM_ICFilter = 6;\/\/ICx_FILTER;<\/span><\/p>\n<p><span style=\"color: #ff6600;\">\u00a0\u00a0\u00a0 TIM_ICInit(TIM2, &amp;TIM_ICInitStructure);<\/span><\/p>\n<p><span style=\"color: #ff6600;\">\u00a0\u00a0\u00a0 \/\/ Clear all pending interrupts<\/span><\/p>\n<p><span style=\"color: #ff6600;\">\u00a0\u00a0\u00a0 TIM_ClearFlag(TIM2, TIM_FLAG_Update);<\/span><\/p>\n<p><span style=\"color: #ff6600;\">\u00a0\u00a0\u00a0 TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);<\/span><\/p>\n<p><span style=\"color: #ff6600;\">\u00a0\u00a0\u00a0 \/\/Reset counter<\/span><\/p>\n<p><span style=\"color: #ff6600;\">\u00a0\u00a0\u00a0 TIM2-&gt;CNT = 10000;\/\/prevent exceeding 0 when turning wheel backwards<\/span><\/p>\n<p><span style=\"color: #ff6600;\">\u00a0\u00a0\u00a0 TIM_Cmd(TIM2, ENABLE);\/\/enable left encoder<\/span><\/p>\n<p><span style=\"color: #ff6600;\">}<\/span><\/p>\n<p>Here are something even simpler:<\/p>\n<p>void Encoder_Configration(void)<br \/>\n{<br \/>\nGPIO_InitTypeDef GPIO_InitStructure;<br \/>\nRCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);<\/p>\n<p>GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;<br \/>\nGPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;<br \/>\nGPIO_InitStructure.GPIO_Pin = GPIO_Pin_15;<br \/>\nGPIO_Init(GPIOA, &amp;GPIO_InitStructure);<br \/>\nGPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;<br \/>\nGPIO_Init(GPIOB, &amp;GPIO_InitStructure);<\/p>\n<p>GPIO_PinAFConfig(GPIOA, GPIO_PinSource15, GPIO_AF_TIM2);<br \/>\nGPIO_PinAFConfig(GPIOB, GPIO_PinSource3, GPIO_AF_TIM2);<\/p>\n<p>TIM_SetAutoreload (TIM2, 0xffffffff);<br \/>\n\/* Configure the timer *\/<\/p>\n<p>TIM_EncoderInterfaceConfig(TIM2, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising, TIM_ICPolarity_Falling);<br \/>\n\/* TIM2 counter enable *\/<br \/>\nTIM_Cmd(TIM2, ENABLE);<br \/>\n}<\/p>\n","protected":false},"excerpt":{"rendered":"<p>For those who use STM32 F10x as the MCU for Micromouse must remember all general purpose timers are 16bits that gave you 65535 max resolution. Since the mouse with fauhalber motor generate about 20000 encoder counts per cell distance traverse, &hellip; <a href=\"http:\/\/micromouseusa.com\/?p=392\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":"","_links_to":"","_links_to_target":""},"categories":[7],"tags":[],"jetpack_featured_media_url":"","_links":{"self":[{"href":"http:\/\/micromouseusa.com\/index.php?rest_route=\/wp\/v2\/posts\/392"}],"collection":[{"href":"http:\/\/micromouseusa.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/micromouseusa.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/micromouseusa.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/micromouseusa.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=392"}],"version-history":[{"count":8,"href":"http:\/\/micromouseusa.com\/index.php?rest_route=\/wp\/v2\/posts\/392\/revisions"}],"predecessor-version":[{"id":2083,"href":"http:\/\/micromouseusa.com\/index.php?rest_route=\/wp\/v2\/posts\/392\/revisions\/2083"}],"wp:attachment":[{"href":"http:\/\/micromouseusa.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=392"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/micromouseusa.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=392"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/micromouseusa.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=392"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}