PROGCONT.RU

Форма входа







Регистрация Вход/

Пример Пример Пример


STM32F инкрементный энкодер подключение к контроллеру и примеры программного кода SPL для его использования.

Во всех контроллерах STM32F имеется множество таймеров и некоторые имеют аппаратный интерфейс для подключения энкодера, найти такие таймеры можно заглянув в описание(datasheet) нужного контроллера.

В описании находим вот такую таблицу где показаны основные свойства всех таймеров.


NO


Именно те таймеры которые имеют счётчики(Counter type) с возможностью счёта Up, down, up/down и имеют на борту интерфейс энкодера.


Ниже примеры программ где показано как должны настраиваться таймеры для работы с механическим и оптическим инкрементным энкодером, для примеров буду используются микроконтроллер STM32F030C8 и LCD с драйвером MAX7219.

Начнём с примера где механический энкодер подключим к TIM3 и выведем информацию поворота на LCD.

Схема подключения.

NOНа данной схеме напряжение подтягивающих резисторов энкодера не должно превышать напряжения питания контроллера.


Код программы.

#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 вольт или меньше.

NO


Код программы для подключения оптического энкодера.

#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 вольт или меньше.

NO


И пример программы для подключения оптического энкодера к 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; } }

Комментариев нет  Только зарегистрированные пользователи могут оставлять комментарии!