STM32F инкрементный энкодер подключение к контроллеру и примеры программного кода SPL для его использования.
Во всех контроллерах STM32F имеется множество таймеров и некоторые имеют аппаратный интерфейс для подключения энкодера, найти такие таймеры можно заглянув в описание(datasheet) нужного контроллера.
В описании находим вот такую таблицу где показаны основные свойства всех таймеров.
Именно те таймеры которые имеют счётчики(Counter type) с возможностью счёта Up, down, up/down и имеют на борту интерфейс энкодера.
Ниже примеры программ где показано как должны настраиваться таймеры для работы с механическим и оптическим инкрементным энкодером, для примеров буду используются микроконтроллер STM32F030C8 и LCD с драйвером MAX7219.
Начнём с примера где механический энкодер подключим к TIM3 и выведем информацию поворота на LCD.
Схема подключения.
На данной схеме напряжение подтягивающих резисторов энкодера не должно превышать напряжения питания контроллера.Код программы.
#include "stm32f0xx.h"
#define Decode_Mode 9
#define Intensity 10
#define Scan_Limit 11
#define Shutdown 12
#define Display_Test 15
void SPI_led_send_data( uint16_t address, uint16_t data);
void LCD_Display( uint32_t data_lcd);
void TIM3_Filter_Value(uint32_t value);
int main(){
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA|RCC_AHBPeriph_GPIOB, ENABLE);
/*Настройка SPI1 для управления LED на MAX7219*/
/*Настраиваем GPIOВ_Pin_4 для стробирования приёма команд и данных по SPI*/
GPIO_InitTypeDef PIN_Strob;
PIN_Strob.GPIO_Mode = GPIO_Mode_OUT;
PIN_Strob.GPIO_OType = GPIO_OType_PP;
PIN_Strob.GPIO_Pin = GPIO_Pin_4;
PIN_Strob.GPIO_PuPd = GPIO_PuPd_NOPULL;
PIN_Strob.GPIO_Speed = GPIO_Speed_Level_3;
GPIO_Init(GPIOB, &PIN_Strob);
GPIO_SetBits(GPIOB, GPIO_Pin_4);
/*Перенаправляем выводы к SPI*/
GPIO_PinAFConfig(GPIOB, GPIO_PinSource3, GPIO_AF_0);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource5, GPIO_AF_0);
/*Настраиваем GPIOВ_Pin_3(SPI1_SCK) и GPIOВ_Pin_5(SPI1_MOSI)*/
GPIO_InitTypeDef SPI1_SCK_MOSI;
SPI1_SCK_MOSI.GPIO_Pin = GPIO_Pin_3|GPIO_Pin_5;
SPI1_SCK_MOSI.GPIO_Mode = GPIO_Mode_AF;
SPI1_SCK_MOSI.GPIO_Speed = GPIO_Speed_Level_3;
SPI1_SCK_MOSI.GPIO_OType = GPIO_OType_PP;
SPI1_SCK_MOSI.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOB, &SPI1_SCK_MOSI);
/*Настраиваем SPI1 как Master и передачу данных по одной линии*/
RCC_APB2PeriphClockCmd( RCC_APB2Periph_SPI1, ENABLE);
SPI_InitTypeDef SPI1_InitStructure;
SPI1_InitStructure.SPI_Direction = SPI_Direction_1Line_Tx;
SPI1_InitStructure.SPI_DataSize = SPI_DataSize_16b;
SPI1_InitStructure.SPI_CPOL = SPI_CPOL_Low;
SPI1_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;
SPI1_InitStructure.SPI_NSS = SPI_NSS_Soft;
SPI1_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;
SPI1_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
SPI1_InitStructure.SPI_Mode = SPI_Mode_Master;
SPI_Init(SPI1, &SPI1_InitStructure);
SPI_Cmd(SPI1, ENABLE);
/*Настраиваем LCD*/
SPI_led_send_data( Shutdown, 1);
SPI_led_send_data( Display_Test, 0);
SPI_led_send_data( Decode_Mode, 255);
SPI_led_send_data( Intensity, 31);
SPI_led_send_data( Scan_Limit, 7);
/*Перенаправляем выводы к TIM3*/
GPIO_PinAFConfig(GPIOA, GPIO_PinSource6, GPIO_AF_1);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource7, GPIO_AF_1);
/*Настраиваем GPIOA_Pin_6(A) и GPIOA_Pin_7(B)*/
GPIO_InitTypeDef GPIO_encoder;
GPIO_encoder.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
GPIO_encoder.GPIO_Mode = GPIO_Mode_AF;
GPIO_encoder.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_encoder.GPIO_OType = GPIO_OType_PP;
GPIO_encoder.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOA, &GPIO_encoder);
/*Настраиваем TIM3 для работы с экондером*/
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
TIM_TimeBaseInitTypeDef TIM3_encoder;
TIM3_encoder.TIM_Period = 65535;
TIM3_encoder.TIM_Prescaler = 0;
TIM3_encoder.TIM_ClockDivision = 0;
TIM3_encoder.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM3, &TIM3_encoder);
TIM_EncoderInterfaceConfig(TIM3, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);
/*Настраиваем входной цифровой фильтр для фаз A и B энкодера, принимаемое значение от 0 до 15*/
TIM3_Filter_Value(15);
TIM_Cmd(TIM3, ENABLE);
while(1){
/*Вынимаем значение поворота энкодера из счётчика TIM3*/
uint32_t count=TIM_GetCounter(TIM3)/4;
LCD_Display(count);
/*Задержка*/
for( uint32_t e=0; e<100000; e++);
}
return 0;
}
/*Функция настройки входного фильтра для выводов TIM3_CH1 и TIM3_CH2*/
void TIM3_Filter_Value(uint32_t value){
TIM3->CCMR1|=(uint32_t)(value<<4);
TIM3->CCMR1|=(uint32_t)(value<<12);
}
/*Функция отправки адреса и данных*/
void SPI_led_send_data( uint16_t address, uint16_t data){
address<<=8;
address|=data;
GPIO_ResetBits(GPIOB, GPIO_Pin_4);
SPI_I2S_SendData16(SPI1, address);
while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_BSY) == SET);
GPIO_SetBits(GPIOB, GPIO_Pin_4);
}
/*Функция вывода счёта на экран LCD*/
void LCD_Display( uint32_t data_lcd){
uint32_t mask=10000000;
/*Цикл вывода информации на LED модуль*/
for( uint8_t i=8; i>0; i--){
SPI_led_send_data( i, (uint8_t)(data_lcd/mask));
data_lcd=data_lcd-(data_lcd/mask*mask);
mask/=10;
}
}
И простая настройка без использования LCD.
#include "stm32f0xx.h"
void TIM3_Filter_Value(uint32_t value);
int main(){
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
/*Перенаправляем выводы к TIM3*/
GPIO_PinAFConfig(GPIOA, GPIO_PinSource6, GPIO_AF_1);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource7, GPIO_AF_1);
/*Настраиваем GPIOA_Pin_6(A) и GPIOA_Pin_7(B)*/
GPIO_InitTypeDef GPIO_encoder;
GPIO_encoder.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
GPIO_encoder.GPIO_Mode = GPIO_Mode_AF;
GPIO_encoder.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_encoder.GPIO_OType = GPIO_OType_PP;
GPIO_encoder.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOA, &GPIO_encoder);
/*Настраиваем TIM3 для работы с экондером*/
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
TIM_TimeBaseInitTypeDef TIM3_encoder;
TIM3_encoder.TIM_Period = 65535;
TIM3_encoder.TIM_Prescaler = 0;
TIM3_encoder.TIM_ClockDivision = 0;
TIM3_encoder.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM3, &TIM3_encoder);
TIM_EncoderInterfaceConfig(TIM3, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);
/*Настраиваем входной цифровой фильтр для фаз A и B энкодера, принимаемое значение от 0 до 15*/
TIM3_Filter_Value(15);
TIM_Cmd(TIM3, ENABLE);
while(1){
/*Вынимаем значение поворота энкодера из счётчика TIM3*/
uint32_t count=TIM_GetCounter(TIM3)/4;
}
return 0;
}
/*Функция настройки входного фильтра для выводов TIM3_CH1 и TIM3_CH2*/
void TIM3_Filter_Value(uint32_t value){
TIM3->CCMR1|=(uint32_t)(value<<4);
TIM3->CCMR1|=(uint32_t)(value<<12);
}
Не большой ликбез по функциям настройки TIM1.
- TIM3_encoder.TIM_Period = 65535
- тут можете поменять 65535 на значение от 0 до 65535, это предел после достижения которого счётчик будет сбрасываться или если зайдёт за нуль выставится опять.
- TIM_EncoderInterfaceConfig(TIM3, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising)
- функция настройки TIM1 для работы в режиме энкодера.
Параметр TIM_EncoderMode_TI12 указывает контроллеру, что нужно фиксировать все события с выводов A и B энкодера, то есть за период четыре значения или например в энкодере 100 рисок а считать будет за один оборот 400. Если изменить его на TIM_EncoderMode_TI1 или TIM_EncoderMode_TI2 то события будут фиксироваться только с вывода TIM3_CH1 или соответственно с TIM3_CH2, за один оборот энкодера будет не 100 рисок а 200.
Параметр TIM_ICPolarity_Rising указывает контроллеру, что сигналы на выводах TIM3_CH1 и TIM3_CH2 не инвертируется, если поменять на TIM_ICPolarity_Falling то сигнал будет изменён на противоположный, попробуйте в функцию поставить вот такую комбинацию TIM_EncoderInterfaceConfig(TIM3, TIM_EncoderMode_TI12, TIM_ICPolarity_Falling, TIM_ICPolarity_Rising) то счёт будет идти в обратном направление.
- TIM3_Filter_Value(15)
- функция устанавливает задержку для отсеивания ложных срабатываний от дребезга контактов энкодера, тут стоит максимальное значение которое рекомендую для механических энкодеров. Для себя можете подобрать опытным путём от 0 до 15, пока не пропадут ложные срабатывания. Функция сделана мной, не забываем добавлять её код из примера в свою программу.
Схема подключения к оптическим энкодерам, механическим которая подойдёт и к магнитным, напряжение питание которых должно быть 5 вольт или меньше.
Код программы для подключения оптического энкодера.
#include "stm32f0xx.h"
#define Decode_Mode 9
#define Intensity 10
#define Scan_Limit 11
#define Shutdown 12
#define Display_Test 15
void SPI_led_send_data( uint16_t address, uint16_t data);
void LCD_Display( uint32_t data_lcd);
void TIM3_Filter_Value(uint32_t value);
int main(){
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);
/*Настройка SPI1 для управления LED на MAX7219*/
/*Настраиваем GPIOВ_Pin_4 для стробирования приёма команд и данных по SPI*/
GPIO_InitTypeDef PIN_Strob;
PIN_Strob.GPIO_Mode = GPIO_Mode_OUT;
PIN_Strob.GPIO_OType = GPIO_OType_PP;
PIN_Strob.GPIO_Pin = GPIO_Pin_14;
PIN_Strob.GPIO_PuPd = GPIO_PuPd_NOPULL;
PIN_Strob.GPIO_Speed = GPIO_Speed_Level_3;
GPIO_Init(GPIOB, &PIN_Strob);
GPIO_SetBits(GPIOB, GPIO_Pin_14);
/*Перенаправляем выводы к SPI*/
GPIO_PinAFConfig(GPIOB, GPIO_PinSource13, GPIO_AF_0);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource15, GPIO_AF_0);
/*Настраиваем GPIOВ_Pin_13(SPI1_SCK) и GPIOВ_Pin_15(SPI1_MOSI)*/
GPIO_InitTypeDef SPI2_SCK_MOSI;
SPI2_SCK_MOSI.GPIO_Pin = GPIO_Pin_13|GPIO_Pin_15;
SPI2_SCK_MOSI.GPIO_Mode = GPIO_Mode_AF;
SPI2_SCK_MOSI.GPIO_Speed = GPIO_Speed_Level_3;
SPI2_SCK_MOSI.GPIO_OType = GPIO_OType_PP;
SPI2_SCK_MOSI.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOB, &SPI2_SCK_MOSI);
/*Настраиваем SPI1 как Master и передачу данных по одной линии*/
RCC_APB1PeriphClockCmd( RCC_APB1Periph_SPI2, ENABLE);
SPI_InitTypeDef SPI2_InitStructure;
SPI2_InitStructure.SPI_Direction = SPI_Direction_1Line_Tx;
SPI2_InitStructure.SPI_DataSize = SPI_DataSize_16b;
SPI2_InitStructure.SPI_CPOL = SPI_CPOL_Low;
SPI2_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;
SPI2_InitStructure.SPI_NSS = SPI_NSS_Soft;
SPI2_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;
SPI2_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
SPI2_InitStructure.SPI_Mode = SPI_Mode_Master;
SPI_Init(SPI2, &SPI2_InitStructure);
SPI_Cmd(SPI2, ENABLE);
/*Настраиваем LCD*/
SPI_led_send_data( Shutdown, 1);
SPI_led_send_data( Display_Test, 0);
SPI_led_send_data( Decode_Mode, 255);
SPI_led_send_data( Intensity, 31);
SPI_led_send_data( Scan_Limit, 7);
/*Перенаправляем выводы к TIM3*/
GPIO_PinAFConfig(GPIOB, GPIO_PinSource4, GPIO_AF_1);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource5, GPIO_AF_1);
/*Настраиваем GPIOB_Pin_4(A) и GPIOB_Pin_5(B)*/
GPIO_InitTypeDef GPIO_encoder;
GPIO_encoder.GPIO_Pin = GPIO_Pin_4|GPIO_Pin_5;
GPIO_encoder.GPIO_Mode = GPIO_Mode_AF;
GPIO_encoder.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_encoder.GPIO_OType = GPIO_OType_PP;
GPIO_encoder.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOB, &GPIO_encoder);
/*Настраиваем TIM3 для работы с экондером*/
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
TIM_TimeBaseInitTypeDef TIM3_encoder;
TIM3_encoder.TIM_Period = 65535;
TIM3_encoder.TIM_Prescaler = 0;
TIM3_encoder.TIM_ClockDivision = 0;
TIM3_encoder.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM3, &TIM3_encoder);
TIM_EncoderInterfaceConfig(TIM3, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);
/*Настраиваем входной цифровой фильтр для фаз A и B энкодера, принимаемое значение от 0 до 15*/
TIM3_Filter_Value(15);
TIM_Cmd(TIM3, ENABLE);
while(1){
/*Вынимаем значение поворота энкодера из счётчика TIM3*/
uint32_t count=TIM_GetCounter(TIM3)/4;
LCD_Display(count);
/*Задержка*/
for( uint32_t e=0; e<100000; e++);
}
return 0;
}
/*Функция настройки входного фильтра для выводов TIM3_CH1 и TIM3_CH2*/
void TIM3_Filter_Value(uint32_t value){
TIM3->CCMR1|=(uint32_t)(value<<4);
TIM3->CCMR1|=(uint32_t)(value<<12);
}
/*Функция отправки адреса и данных*/
void SPI_led_send_data( uint16_t address, uint16_t data){
address<<=8;
address|=data;
GPIO_ResetBits(GPIOB, GPIO_Pin_14);
SPI_I2S_SendData16(SPI2, address);
while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_BSY) == SET);
GPIO_SetBits(GPIOB, GPIO_Pin_14);
}
/*Функция вывода счёта на экран LCD*/
void LCD_Display( uint32_t data_lcd){
uint32_t mask=10000000;
/*Цикл вывода информации на LED модуль*/
for( uint8_t i=8; i>0; i--){
SPI_led_send_data( i, (uint8_t)(data_lcd/mask));
data_lcd=data_lcd-(data_lcd/mask*mask);
mask/=10;
}
}
Тут отсутствуют на выходах энкодера конденсаторы как у механических, они здесь могут навредить так как будут задерживать спад или подъём выходящего сигнала, что вызовет пропуски счета на больших оборотах энкодера. Для исключения помех на проводах A и B энкодера они должны быть обязательно экранированы.
Код программы аналогичен механическим энкодерам за исключением установки фильтра входящих выводов, тут должно быть так TIM3_Filter_Value(0) потому, что скорость и разрешение энкодеров могут быть большими поэтому задержка фильтра будет здесь вредить.
В энкодерах оптических и магнитных могут отсутствовать выходные схемы которые выравнивают сигнал, делают его квадратурным, с контроллерами не нужно использовать дополнительные схемы для выравнивания сигналов так как их входы цифровые и имеют встроенный гистерезис.
Схема для подключения к TIM1 оптического энкодера, механического и магнитного, напряжение питание которых должно быть 5 вольт или меньше.
И пример программы для подключения оптического энкодера к TIM1, если будете подключать механический то задержку для входного фильтра поставьте 15.
#include "stm32f0xx.h"
#define Decode_Mode 9
#define Intensity 10
#define Scan_Limit 11
#define Shutdown 12
#define Display_Test 15
void SPI_led_send_data( uint16_t address, uint16_t data);
void LCD_Display( uint32_t data_lcd);
void TIM1_Filter_Value(uint32_t value);
int main(){
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA|RCC_AHBPeriph_GPIOB, ENABLE);
/*Настройка SPI1 для управления LED на MAX7219*/
/*Настраиваем GPIOВ_Pin_4 для стробирования приёма команд и данных по SPI*/
GPIO_InitTypeDef PIN_Strob;
PIN_Strob.GPIO_Mode = GPIO_Mode_OUT;
PIN_Strob.GPIO_OType = GPIO_OType_PP;
PIN_Strob.GPIO_Pin = GPIO_Pin_4;
PIN_Strob.GPIO_PuPd = GPIO_PuPd_NOPULL;
PIN_Strob.GPIO_Speed = GPIO_Speed_Level_3;
GPIO_Init(GPIOB, &PIN_Strob);
GPIO_SetBits(GPIOB, GPIO_Pin_4);
/*Перенаправляем выводы к SPI*/
GPIO_PinAFConfig(GPIOB, GPIO_PinSource3, GPIO_AF_0);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource5, GPIO_AF_0);
/*Настраиваем GPIOВ_Pin_3(SPI1_SCK) и GPIOВ_Pin_5(SPI1_MOSI)*/
GPIO_InitTypeDef SPI1_SCK_MOSI;
SPI1_SCK_MOSI.GPIO_Pin = GPIO_Pin_3|GPIO_Pin_5;
SPI1_SCK_MOSI.GPIO_Mode = GPIO_Mode_AF;
SPI1_SCK_MOSI.GPIO_Speed = GPIO_Speed_Level_3;
SPI1_SCK_MOSI.GPIO_OType = GPIO_OType_PP;
SPI1_SCK_MOSI.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOB, &SPI1_SCK_MOSI);
/*Настраиваем SPI1 как Master и передачу данных по одной линии*/
RCC_APB2PeriphClockCmd( RCC_APB2Periph_SPI1, ENABLE);
SPI_InitTypeDef SPI1_InitStructure;
SPI1_InitStructure.SPI_Direction = SPI_Direction_1Line_Tx;
SPI1_InitStructure.SPI_DataSize = SPI_DataSize_16b;
SPI1_InitStructure.SPI_CPOL = SPI_CPOL_Low;
SPI1_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;
SPI1_InitStructure.SPI_NSS = SPI_NSS_Soft;
SPI1_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;
SPI1_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
SPI1_InitStructure.SPI_Mode = SPI_Mode_Master;
SPI_Init(SPI1, &SPI1_InitStructure);
SPI_Cmd(SPI1, ENABLE);
/*Настраиваем LCD*/
SPI_led_send_data( Shutdown, 1);
SPI_led_send_data( Display_Test, 0);
SPI_led_send_data( Decode_Mode, 255);
SPI_led_send_data( Intensity, 31);
SPI_led_send_data( Scan_Limit, 7);
/*Перенаправляем выводы к TIM1*/
GPIO_PinAFConfig(GPIOA, GPIO_PinSource8, GPIO_AF_2);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_2);
/*Настраиваем GPIOA_Pin_8(A) и GPIOA_Pin_9(B)*/
GPIO_InitTypeDef GPIO_encoder;
GPIO_encoder.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9;
GPIO_encoder.GPIO_Mode = GPIO_Mode_AF;
GPIO_encoder.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_encoder.GPIO_OType = GPIO_OType_PP;
GPIO_encoder.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOA, &GPIO_encoder);
/*Настраиваем TIM1 для работы с экондером*/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
TIM_TimeBaseInitTypeDef TIM1_encoder;
TIM1_encoder.TIM_Period = 65535;
TIM1_encoder.TIM_Prescaler = 0;
TIM1_encoder.TIM_ClockDivision = 0;
TIM1_encoder.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM1, &TIM1_encoder);
TIM_EncoderInterfaceConfig(TIM1, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);
/*Настраиваем входной цифровой фильтр для фаз A и B энкодера, принимаемое значение от 0 до 15*/
TIM1_Filter_Value(0);
TIM_Cmd(TIM1, ENABLE);
while(1){
/*Вынимаем значение поворота энкодера из счётчика TIM1*/
uint32_t count=TIM_GetCounter(TIM1)/4;
LCD_Display(count);
/*Задержка*/
for( uint32_t e=0; e<100000; e++);
}
return 0;
}
/*Функция настройки входного фильтра для выводов TIM1_CH1 и TIM1_CH2*/
void TIM1_Filter_Value(uint32_t value){
TIM1->CCMR1|=(uint32_t)(value<<4);
TIM1->CCMR1|=(uint32_t)(value<<12);
}
/*Функция отправки адреса и данных*/
void SPI_led_send_data( uint16_t address, uint16_t data){
address<<=8;
address|=data;
GPIO_ResetBits(GPIOB, GPIO_Pin_4);
SPI_I2S_SendData16(SPI1, address);
while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_BSY) == SET);
GPIO_SetBits(GPIOB, GPIO_Pin_4);
}
/*Функция вывода счёта на экран LCD*/
void LCD_Display( uint32_t data_lcd){
uint32_t mask=10000000;
/*Цикл вывода информации на LED модуль*/
for( uint8_t i=8; i>0; i--){
SPI_led_send_data( i, (uint8_t)(data_lcd/mask));
data_lcd=data_lcd-(data_lcd/mask*mask);
mask/=10;
}
}