Отчет по лабораторной работе. Программа реализует включения встроенного на отладочной плате светодиода по нажатии и удержании кнопки
Скачать 254.96 Kb.
|
SysTick_CTRL_ENABLE_Pos; ОТЧЁТ По дисциплине: Микроконтроллеры в кибернитических системах Подготовил: Студент группы 91-УТ Кочергин Максим Юрьевич Мигание светодиодом с помощью кнопки. Программа реализует включения встроенного на отладочной плате светодиода по нажатии и удержании кнопки. Т.к на отладочной плате кнопка SW1 подключена к порту C, он будет инициализироваться, как порт на вход и будет считывать сигнал нажата кнопка, или нет. #include "MDR32Fx.h" #include "core_cm3.h" #include "MDR32F9Qx_config.h" #include "system_MDR32F9Qx.h" #include "MDR32F9Qx_rst_clk.h" #include "MDR32F9Qx_port.h" #define LED1 PORT_Pin_0 //определить нулевой вывод как LED1 static PORT_InitTypeDef PortInit; //объявление структуры int main(){ RST_CLK_PCLKcmd(RST_CLK_PCLK_PORTC, ENABLE);//включить тактирование порта С RST_CLK_PCLKcmd(RST_CLK_PCLK_PORTFB, ENABLE); );//включить тактирование порта B //Инициализация порта С на вход PortInit.PORT_OE = PORT_OE_IN; // направление передачи данных = вход PortInit.PORT_FUNC = PORT_FUNC_PORT; // режим работы вывода порта = Порт PortInit.PORT_MODE = PORT_MODE_DIGITAL; // режим работы выводе = цифровой PortInit.PORT_SPEED = PORT_SPEED_SLOW; // скорость фронта вывода = медленный PortInit.PORT_Pin = (PORT_Pin_2); // выбор вывода 2 для инициализации PORT_Init(MDR_PORTC, &PortInit); //инициализация порта С заданными параметрами //Инициализация порта B на выход PortInit.PORT_OE = PORT_OE_OUT; // направление передачи данных = Выход PortInit.PORT_FUNC = PORT_FUNC_PORT; // режим работы вывода порта = Порт PortInit.PORT_MODE = PORT_MODE_DIGITAL; // режим работы вывода = Цифровой PortInit.PORT_SPEED = PORT_SPEED_SLOW; // скорость фронта вывода = медленный PortInit.PORT_Pin = (PORT_Pin_all);// выбор всех выводов для инициализации PORT_Init(MDR_PORTB, &PortInit); //инициализация порта B заданными параметрами while(1){ //бесконечный цикл if (PORT_ReadInputDataBit(MDR_PORTC,PORT_Pin_2) == 0) //если кнопка не нажата… { PORT_SetBits(MDR_PORTB, LED1); // включить светодиод на выводе 0 порта B } else //иначе { PORT_ResetBits(MDR_PORTB, LED1); // выключить светодиод на выводе 0 порта B } } } Сначала в программе подключаются бибилиотеки, Затем определяется постоянная LED1 к которой привязывается значение Port_pin_0 ( порт под номером 0) Затем объявляется структура инициализации портов. Далее инициализируются сами порты Порт С на вход. Светодиоды на Плате подключены к порту B Поэтому следом мы инициализируем его, и определяем выходным. Сама программа реализуется с помощью бесконечного цикла образованного функцией while(1) Затем с помощью функции (PORT_ReadInputDataBit(MDR_PORTC,PORT_Pin_2) == 0) Мы считываем значение с кнопки SW1 расположенной на пине 2 порта C А затем с помощью функций PORT_SetBits(MDR_PORTB, LED1); Мы устанавливаем бит ( 1 ) в 0вой пин порта B (Зажигаем светодиод) PORT_ResetBits(MDR_PORTB, LED1); Мы очищаем бит (0) в 0вой пин порта B (перестаём подавать напряжение на светодиод Мигание светодиодами с помощью разных кнопок. При нажатии кнопок должны загораться лишь определённые светодиоды При нажатии кнопки SW1 будут загораться светодиоды VD5 и VD7 При нажатии кнопки SW3 будут загораться светодиоды VD4 и VD6 А при нажатии кнопки SW4 будут загораться светодиоды VD(4-7) #include "MDR32Fx.h" #include "core_cm3.h" #include "MDR32F9Qx_config.h" #include "system_MDR32F9Qx.h" #include "MDR32F9Qx_rst_clk.h" #include "MDR32F9Qx_port.h" #define LED1 PORT_Pin_0 //определить нулевой пин как LED1 #define LED2 PORT_Pin_1 //определить первый пин как LED2 #define LED3 PORT_Pin_2 //определить второй пин как LED3 #define LED4 PORT_Pin_3 //определить третий пин как LED4 static PORT_InitTypeDef PortInit; //объявление структуры int main(){ RST_CLK_PCLKcmd(RST_CLK_PCLK_PORTC, ENABLE);//включить тактирование порта С RST_CLK_PCLKcmd(RST_CLK_PCLK_PORTC, ENABLE);//включить тактирование порта E RST_CLK_PCLKcmd(RST_CLK_PCLK_PORTFB, ENABLE); );//включить тактирование порта B //Инициализация порта С на вход PortInit.PORT_OE = PORT_OE_IN; // направление передачи данных = вход PortInit.PORT_FUNC = PORT_FUNC_PORT; // режим работы вывода порта = Порт PortInit.PORT_MODE = PORT_MODE_DIGITAL; // режим работы выводе = цифровой PortInit.PORT_SPEED = PORT_SPEED_SLOW; // скорость фронта вывода = медленный PortInit.PORT_Pin = (PORT_Pin_2); // выбор вывода 2 для инициализации PORT_Init(MDR_PORTC, &PortInit); //инициализация порта С заданными параметрами PortInit.PORT_Pin = (PORT_Pin_1); // выбор вывода 1 для инициализации PORT_Init(MDR_PORTE, &PortInit); //инициализация порта E заданными параметрами PortInit.PORT_Pin = (PORT_Pin_3); // выбор вывода 3 для инициализации PORT_Init(MDR_PORTE, &PortInit); //инициализация порта E заданными параметрами //Инициализация порта B на выход PortInit.PORT_OE = PORT_OE_OUT; // направление передачи данных = Выход PortInit.PORT_FUNC = PORT_FUNC_PORT; // режим работы вывода порта = Порт PortInit.PORT_MODE = PORT_MODE_DIGITAL; // режим работы вывода = Цифровой PortInit.PORT_SPEED = PORT_SPEED_SLOW; // скорость фронта вывода = медленный PortInit.PORT_Pin = (PORT_Pin_all);// выбор всех выводов для инициализации PORT_Init(MDR_PORTB, &PortInit); //инициализация порта B заданными параметрами while(1){ //бесконечный цикл if (PORT_ReadInputDataBit(MDR_PORTC,PORT_Pin_2) == 0) //если кнопка не нажата… { PORT_SetBits(MDR_PORTB, LED1); PORT_SetBits(MDR_PORTB, LED3); } else //иначе { PORT_ResetBits(MDR_PORTB, port_pin_all); // выключить все светодиоды } if (PORT_ReadInputDataBit(MDR_PORTE,PORT_Pin_1) == 0) { PORT_SetBits(MDR_PORTB, LED2); PORT_SetBits(MDR_PORTB, LED4); } else { PORT_ResetBits(MDR_PORTB, PORT_Pin_all); } if (PORT_ReadInputDataBit(MDR_PORTE,PORT_Pin_3) == 0) { PORT_SetBits(MDR_PORTB, PORT_Pin_all); } else { PORT_ResetBits(MDR_PORTB, port_pin_all); } } } В данной программе дополнительно подключается порт E т.к к нему на плате подключены кнопки SW3 и SW4. Кнопку SW2 использовать нельзя. Она подключена к порту b и по условию он инициализируются как порт на выход т.к к нему подключены светодиоды Светодиоды, мигающие раз в секундуК выводам 0 и 1 порта B подключены светодиоды(VD2 и VD3), которые должны переключаться раз в секунду. Это можно сделать с помощью прерываний при переполнении системного таймера SysTick. #include "MDR32Fx.h" #include "core_cm3.h" #include "MDR32F9Qx_config.h" #include "system_MDR32F9Qx.h" #include "MDR32F9Qx_rst_clk.h" #include "MDR32F9Qx_port.h" static PORT_InitTypeDef PortInit;//объявление структуры PortInit volatile uint32_t delay_dec = 0;// объявление переменной delay_dec //Обработчик прерывания системного таймера void SysTick_Handler (void) { if (delay_dec !=0) delay_dec--;//вычитать из delay_dec, пока не станет равен 0 } //функцияв ременной задержки void delay_ms (uint32_t delay_ms) { delay_dec = delay_ms;//присвоить delay_dec значение delay_ms while (delay_dec) {}; // выполнять функцию пока delay_dec не станет равным 0 } int main(){ RST_CLK_PCLKcmd(RST_CLK_PCLK_PORTB, ENABLE); );//включить тактирование порта B //Инициализация порта F на выход PortInit.PORT_OE = PORT_OE_OUT; // направление передачи данных = Выход PortInit.PORT_FUNC = PORT_FUNC_PORT; // режим работы вывода порта = Порт PortInit.PORT_MODE = PORT_MODE_DIGITAL; // режим работы вывода= цифровой PortInit.PORT_SPEED = PORT_SPEED_SLOW; // скорость фронта вывода = медленная PortInit.PORT_Pin = (PORT_Pin_All);// выбор вывода для инициализации PORT_Init(MDR_PORTB, &PortInit); //инициализация порта B заданными параметрами //Инициализация системного таймера SysTick->LOAD |= (8000000/1000)-1; //значение задержки прерывания при тактовой частоте 8 МГц = 1мс SysTick->CTRL |= SysTick_CTRL_CLKSOURCE_Pos; //источник тактирования HCLK SysTick->CTRL |= SysTick_CTRL_COUNTFLAG_Pos;// при досчитывании до нуля таймер генерирует прерывание SysTick->CTRL |= RST_CLK_PCLKcmd(RST_CLK_PCLK_PORTB,ENABLE); );//включить тактирование порта F //Инициализация порта F для функции UART PortInit.PORT_PULL_UP = PORT_PULL_UP_OFF;//подтяжка в питание выключена PortInit.PORT_PULL_DOWN = PORT_PULL_DOWN_OFF;//подтяжка в ноль выключена PortInit.PORT_PD_SHM = PORT_PD_SHM_OFF;//режим триггера Шмитта выключен PortInit.PORT_PD = PORT_PD_DRIVER;//режим управляемого драйвера PortInit.PORT_GFEN = PORT_GFEN_OFF;//входной фильтр выключен PortInit.PORT_FUNC = PORT_FUNC_ALTER;//альтернативная функция порта PortInit.PORT_SPEED = PORT_SPEED_MAXFAST;//скорость фронта вывода = быстрая PortInit.PORT_MODE = PORT_MODE_DIGITAL; //режим работы вывода = цифровой //Инициализация вывода 1 как UART_TX PortInit.PORT_Pin = PORT_Pin_1; PORT_Init(MDR_PORTF, &PortInit); //Инициализация вывода 0 как UART_RX PortInit.PORT_OE = PORT_OE_IN; PortInit.PORT_Pin = PORT_Pin_0; PORT_Init(MDR_PORTF, &PortInit); RST_CLK_CPU_PLLconfig (RST_CLK_CPU_PLLsrcHSIdiv2,0);//конфигурация источника тактирования HSI делением частоты на 2 и без умножения RST_CLK_PCLKcmd(RST_CLK_PCLK_UART1, ENABLE); );//включить тактирование UART1 UART_BRGInit(MDR_UART1, UART_HCLKdiv1);//делитель тактовой частоты UART = 1 //КонфигурацияUART UART_InitStructure.UART_BaudRate = 115000; //скорость передачи данных 15000 бод/сек UART_InitStructure.UART_WordLength = UART_WordLength8b;//длина слова в посылке = 8бит UART_InitStructure.UART_StopBits = UART_StopBits1;//один стоповый бит UART_InitStructure.UART_Parity = UART_Parity_No;//без проверки четности UART_InitStructure.UART_FIFOMode = UART_FIFO_ON;//включить работу буфера FIFO приемника и передачи UART_InitStructure.UART_HardwareFlowControl = UART_HardwareFlowControl_RXE | UART_HardwareFlowControl_TXE;//Разрешить прием, разрешить передачу данных //ИнициализацияUART1 с заданными параметрами UART_Init (MDR_UART1,&UART_InitStructure); UART_Cmd(MDR_UART1,ENABLE); //включить сконфигурированный UART while (1) //бесконечный цикл { UART_SendData (MDR_UART1, i++); //Послать значение счетчика по UART1, и прибавить к нему 1 delay_ms(5000);//подождать 5 секунд } } Приём Сигналов на компьютер осуществляется с помощью программы terminal. Для этого в ней требуется точно указать конфигурацию порта, к которому подключается микроконтроллер. Должны совпадать скорость передачи данных, количество битов в “слове” количество стоповых битов, функция проверки четности и т.д. Включение и выключение светодиода с помощью ПК по интерфейсу RS-232 Вывод 1 порта F назначен в качестве линии передачи TXD приемопередатчика UART1, а вывод 0 того же порта – в качестве линии приема RXD. К выводам 0 и 1 порта B подключены светодиоды VD5 и VD4. При получении определенной команды от ПК по интерфейсу RS-232 происходит включение или выключение светодиодов. Код команды и ее описание представлены в таблице 4. Прием команды микроконтроллером от ПК по интерфейсу RS-232 реализован на основе сигнала прерывания . Таблица4 – Описание команд управления светодиодами
#include "MDR32F9Qx_config.h" #include "MDR32Fx.h" #include "MDR32F9Qx_uart.h" #include "MDR32F9Qx_port.h" #include "MDR32F9Qx_rst_clk.h" #include "core_cm3.h" #include "system_MDR32F9Qx.h static PORT_InitTypeDef PortInit;//объявление структуры PortInit static UART_InitTypeDef UART_InitStructure;//объявление структуры UART_InitStructure uint8_t Recieve_buff[256]; //объявление массива Recieve_buff, выполняющего роль буфера для приема uint8_t Recieve_Wr = 0,Recieve_Rd = 0,Recieve_Cnt = 0; //Recieve_Wr – счетчик при записи элемента в массив, //Recieve_Rd – счетчик при чтении элемента из массива, //Recieve_Cnt –общий счетчик обработанных элементов массива. // Обработчик прерывания UART void UART1_IRQHandler (void) { if(UART_GetITStatus(MDR_UART1, UART_IT_RX == 1 ))//если сигнал прерывания от приема нового пакета { UART_ClearITPendingBit(MDR_UART1, UART_IT_RX); //сбросить флаг прерывания Recieve_buff[Recieve_Wr] = UART_ReceiveData(MDR_UART1); //записать полученные данные в массив Recieve_buff Recieve_Wr++; //увеличитьRecieve_Wr Recieve_Cnt++; //увеличить Recieve_Cnt } } //Функция инициализации светодиодов void init_leds(void) { RST_CLK_PCLKcmd(RST_CLK_PCLK_PORTB, ENABLE); PortInit.PORT_Pin = PORT_Pin_0|PORT_Pin_1; PortInit.PORT_OE = PORT_OE_OUT; PortInit.PORT_FUNC = PORT_FUNC_PORT; PortInit.PORT_MODE = PORT_MODE_DIGITAL; PortInit.PORT_SPEED = PORT_SPEED_FAST; PORT_Init(MDR_PORTB, &PortInit); } //Функция инициализации UART void init_UART(void) { RST_CLK_PCLKcmd(RST_CLK_PCLK_PORTF,ENABLE); PortInit.PORT_PULL_UP = PORT_PULL_UP_OFF; PortInit.PORT_PULL_DOWN = PORT_PULL_DOWN_OFF; PortInit.PORT_PD_SHM = PORT_PD_SHM_OFF; PortInit.PORT_PD = PORT_PD_DRIVER; PortInit.PORT_GFEN = PORT_GFEN_OFF; PortInit.PORT_FUNC = PORT_FUNC_ALTER; PortInit.PORT_SPEED = PORT_SPEED_MAXFAST; PortInit.PORT_MODE = PORT_MODE_DIGITAL; PortInit.PORT_Pin = PORT_Pin_1; PORT_Init(MDR_PORTF, &PortInit); PortInit.PORT_Pin = PORT_Pin_0; PORT_Init(MDR_PORTF, &PortInit); RST_CLK_CPU_PLLconfig (RST_CLK_CPU_PLLsrcHSIdiv2,0); RST_CLK_PCLKcmd(RST_CLK_PCLK_UART1, ENABLE); UART_BRGInit(MDR_UART1, UART_HCLKdiv1); UART_InitStructure.UART_BaudRate = 115000; UART_InitStructure.UART_WordLength = UART_WordLength8b; UART_InitStructure.UART_StopBits = UART_StopBits1; UART_InitStructure.UART_Parity = UART_Parity_No; UART_InitStructure.UART_FIFOMode = UART_FIFO_OFF; UART_InitStructure.UART_HardwareFlowControl = UART_HardwareFlowControl_RXE | UART_HardwareFlowControl_TXE; UART_Init (MDR_UART1,&UART_InitStructure); UART_Cmd(MDR_UART1,ENABLE); NVIC_EnableIRQ(UART1_IRQn);//включить прерывания UART UART_ITConfig(MDR_UART1,UART_IT_RX, ENABLE);//включить прерывания по приходу нового пакета вUART } int main (void) { init_leds(); //инициализация светодиодов init_UART();// инициализацияUART while (1) //бесконечный цикл { if(Recieve_Cnt> 0) //если общий счетчик больше 0, т.е. в массиве Recieve_buff есть необработанные данные, выполнить обработку в машине состояний switch-case в соответствии с таблицей 4. { switch(Recieve_buff[Recieve_Rd]){ case 0x0A : PORT_SetBits(MDR_PORTB, PORT_Pin_0); break; case 0x1A : PORT_ResetBits(MDR_PORTB, PORT_Pin_0); break; case 0x0B : PORT_SetBits(MDR_PORTB, PORT_Pin_1); break; case 0x1B : PORT_ResetBits(MDR_PORTB, PORT_Pin_1); break; case 0xAA : PORT_SetBits(MDR_PORTB, PORT_Pin_0|PORT_Pin_1); break; case 0x11 : PORT_ResetBits(MDR_PORTB,PORT_Pin_0|PORT_Pin_1); break; default : break; } Recieve_Rd++; //увеличить Recieve_Rd Recieve_Cnt--;// уменьшить Recieve_Cnt } } } Управление яркостью свечения светодиода с помощью программной реализации широтно-импульсной модуляцииШиротно-Импульсная Модуляция (ШИМ) – управление средней мощностью нагрузки с помощью серии высокочастотных импульсов. Регулируется усреднённая мощность изменением длительности импульсов и пауз между ними. Чем длиннее импульсы и короче паузы между ними, тем средняя мощность в нагрузке выше. ШИМ – простой случай цифро-аналогового преобразования – плавного управления напряжением или мощностью цифровыми схемами, имеющими только два состояния. ШИМ представляет собой импульсный сигнал постоянной частоты и переменной скважности (отношение длительности импульса к периоду его следования). С помощью задания скважности можно менять среднее напряжение на выходе ШИМ. Таким способом, меняя выходную мощность, можно управлять яркостью светодиода. К выводу 0 порта B подключен светодиод VD5. К выводу 2 порта C подключена кнопка SW1. С помощью метода широтно-импульсной модуляции будем управлять яркостью светодиода. Кнопка SW1 задает уровень скважности. ШИМ генерируется на основе 8 разрядного счетчика заданного переменной PWM_Counter. #include "MDR32F9Qx_config.h" #include "MDR32Fx.h" #include "MDR32F9Qx_rst_clk.h" #include "MDR32F9Qx_port.h" #define LED1 PORT_Pin_0 //ОпределитьPORT_Pin_0 как LED1 #define Button_1 PORT_Pin_2 static PORT_InitTypeDefPortInit; //Функция инициализации порта B на выход void init_leds() { RST_CLK_PCLKcmd(RST_CLK_PCLK_PORTB, ENABLE); PortInit.PORT_Pin = (LED1); PortInit.PORT_OE = PORT_OE_OUT; PortInit.PORT_FUNC = PORT_FUNC_PORT; PortInit.PORT_MODE = PORT_MODE_DIGITAL; PortInit.PORT_SPEED = PORT_SPEED_FAST; PORT_Init(MDR_PORTB,&PortInit); } //Функция инициализация порта С на вход void init_button() { RST_CLK_PCLKcmd(RST_CLK_PCLK_PORTC, ENABLE); PortInit.PORT_Pin = (Button_1); PortInit.PORT_OE = PORT_OE_IN; PortInit.PORT_FUNC = PORT_FUNC_PORT; PortInit.PORT_MODE = PORT_MODE_DIGITAL; PortInit.PORT_SPEED = PORT_SPEED_FAST; PORT_Init(MDR_PORTC, &PortInit); } uint8_t PWM_Counter = 0; //объявление счетчика PWM_Counter uint8_t PWM_A = 0; //объявление переменной PWM_A (задает длительность импульса) uint8_t PWM_B = 40; //объявление переменной PWM_B (задает период импульса) static uint8_t btn_old_state = 0; //переменная, хранящая предыдущее состояние кнопки static uint8_t btn_state; //переменная, хранящая текущее состояние кнопки int main(){ init_leds(); //инициализация светодиода init_button();////инициализация кнопки while(1){ //бесконечный цикл //Увеличение переменной PWM_A только в момент нажатия кнопки btn_state = PORT_ReadInputDataBit(MDR_PORTC, Button_1); //запомнить текущее состояние кнопки (нажата или нет) if(btn_old_state == 0 && btn_state == 1)//если кнопка была не нажата, а теперь нажата { PWM_A++;м // увеличитьPWM_A if(PWM_A >=PWM_B) // если досчитали до значенияPWM_B { PWM_A = 0; //сбросить в ноль } } btn_old_state = btn_state; // запомнить предыдущее состояние кнопки //Генерация ШИМ if(PWM_Counter>= PWM_B) //если счетчик досчитал до значения PWM_B
//выключить светодиод }else { //иначе PWM_Counter++; //увеличить счетчик } } } Управление яркостью свечения светодиода с помощью программной реализации широтно-импульсной модуляцииПо нажатии одной кнопки SW1 светодиод должен увеличивать свою яркость, а по нажатию кнопки SW3 светодиод должен уменьшать свою яркость. #include "MDR32F9Qx_config.h" #include "MDR32Fx.h" #include "MDR32F9Qx_rst_clk.h" #include "MDR32F9Qx_port.h" #define LED1 PORT_Pin_0 //ОпределитьPORT_Pin_0 как LED1 #define Button_1 PORT_Pin_2 #define Button_1 PORT_Pin_1 static PORT_InitTypeDefPortInit; //Функция инициализации порта B на выход void init_leds() { RST_CLK_PCLKcmd(RST_CLK_PCLK_PORTB, ENABLE); PortInit.PORT_Pin = (LED1); PortInit.PORT_OE = PORT_OE_OUT; PortInit.PORT_FUNC = PORT_FUNC_PORT; PortInit.PORT_MODE = PORT_MODE_DIGITAL; PortInit.PORT_SPEED = PORT_SPEED_FAST; PORT_Init(MDR_PORTB,&PortInit); } //Функция инициализация порта С на вход void init_buttons() { RST_CLK_PCLKcmd(RST_CLK_PCLK_PORTE, ENABLE); RST_CLK_PCLKcmd(RST_CLK_PCLK_PORTC, ENABLE); PortInit.PORT_Pin = (Button_1); PortInit.PORT_OE = PORT_OE_IN; PortInit.PORT_FUNC = PORT_FUNC_PORT; PortInit.PORT_MODE = PORT_MODE_DIGITAL; PortInit.PORT_SPEED = PORT_SPEED_FAST; PORT_Init(MDR_PORTC, &PortInit); PortInit.PORT_Pin = (Button_2); PORT_Init(MDR_PORTE, &PortInit); } uint8_t PWM_Counter = 0; //объявление счетчика PWM_Counter uint8_t PWM_A = 0; //объявление переменной PWM_A (задает длительность импульса) uint8_t PWM_B = 40; //объявление переменной PWM_B (задает период импульса) uint8_t PWM_С = 0; //объявление переменной PWM_С ( нужна для отсчёта минимума PWM_A static uint8_t btn_old_state = 0; //переменная, хранящая предыдущее состояние кнопки1 static uint8_t btn_state; //переменная, хранящая текущее состояние кнопки1 static uint8_t btn_old_state2 = 0; //переменная, хранящая предыдущее состояние кнопки2 static uint8_t btn_state2; //переменная, хранящая текущее состояние кнопки2 int main(){ init_leds(); //инициализация светодиода init_button();////инициализация кнопки while(1){ //бесконечный цикл //Увеличение переменной PWM_A только в момент нажатия кнопки btn_state = PORT_ReadInputDataBit(MDR_PORTC, Button_1); btn_state2 = PORT_ReadInputDataBit(MDR_PORTE, Button_2); //запомнить текущее состояние кнопки (нажата или нет) if(btn_old_state == 0 && btn_state == 1)//если кнопка была не нажата, а теперь нажата { PWM_A++;м // увеличитьPWM_A if(PWM_A >=PWM_B) // если досчитали до значенияPWM_B { PWM_A = 0; //сбросить в ноль } } if(btn_old_state2 == 0 && btn_state2 == 1 { PWM_A--;м if(PWM_A <=PWM_C) // если досчитали до значенияPWM_C { PWM_A = 39; // увеличить до макимума } } btn_old_state = btn_state; // запомнить предыдущее состояние кнопки btn_old_state2 = btn_state2; // запомнить предыдущее состояние кнопки //Генерация ШИМ if(PWM_Counter>= PWM_B) //если счетчик досчитал до значения PWM_B
//выключить светодиод }else { //иначе PWM_Counter++; //увеличить счетчик } } } Аппаратная реализация широтно-импульсной модуляцииВ общем случае рекомендуется реализовывать аппаратный ШИМ микроконтроллера на основе прерываний от счетчика таймера. Таймер микроконтроллера работает независимо от центрального процессора и в таком случае не требует дополнительных вычислительных ресурсов. На выводах 1, 2, 3, 4, 5 порта А располагается каналы 1, 2 и 3 таймера1, которые могут быть сконфигурированы в режиме ШИМ. Зафиксировать сигнал ШИМ с разной скважностью можно на ножках 7, 8, 9, 10,12 разъема Х25 с помощью цифрового осциллографа. #include "MDR32F9Qx_config.h" #include "MDR32Fx.h" #include "MDR32F9Qx_timer.h" #include "MDR32F9Qx_rst_clk.h" #include "MDR32F9Qx_port.h" TIMER_CntInitTypeDef sTIM_CntInit; TIMER_ChnInitTypeDef sTIM_ChnInit; TIMER_ChnOutInitTypeDef sTIM_ChnOutInit; PORT_InitTypeDef PORT_InitStructure; uint16_t CCR1_Val = 500; uint16_t CCR2_Val = 1000; uint16_t CCR3_Val = 2000; int main(void) { RST_CLK_PCLKcmd((RST_CLK_PCLK_RST_CLK),ENABLE); RST_CLK_PCLKcmd((RST_CLK_PCLK_TIMER1), ENABLE); RST_CLK_PCLKcmd((RST_CLK_PCLK_PORTA), ENABLE); PORT_InitStructure.PORT_Pin = (PORT_Pin_1 | PORT_Pin_2 | PORT_Pin_3 | PORT_Pin_4 | PORT_Pin_5); PORT_InitStructure.PORT_OE = PORT_OE_OUT; PORT_InitStructure.PORT_FUNC = PORT_FUNC_ALTER; PORT_InitStructure.PORT_MODE = PORT_MODE_DIGITAL; PORT_InitStructure.PORT_SPEED = PORT_SPEED_FAST; PORT_Init(MDR_PORTA, &PORT_InitStructure); /* TIM1CLK = 8 MHz, Prescaler = 0, TIM1 counter clock = 8 MHz TIM1 = TIM1CLK/(TIM1_Period + 1) = 1.95 KHz TIM1 = TIM1->CCR1 / (TIM1_Period +1) = 12.5% TIM1 = TIM1->CCR2 / (TIM1_Period +1) = 25% TIM1 = TIM1->CCR3 / (TIM1_Period + 1) = 50% */ sTIM_CntInit.TIMER_Prescaler = 0x0; sTIM_CntInit.TIMER_Period = 4000; sTIM_CntInit.TIMER_CounterMode = TIMER_CntMode_ClkFixedDir; sTIM_CntInit.TIMER_CounterDirection = TIMER_CntDir_Up; sTIM_CntInit.TIMER_EventSource = TIMER_EvSrc_None; sTIM_CntInit.TIMER_FilterSampling = TIMER_FDTS_TIMER_CLK_div_1; sTIM_CntInit.TIMER_ARR_UpdateMode =TIMER_ARR_Update_Immediately; sTIM_CntInit.TIMER_ETR_FilterConf =TIMER_Filter_1FF_at_TIMER_CLK; sTIM_CntInit.TIMER_ETR_Prescaler = TIMER_ETR_Prescaler_None; sTIM_CntInit.TIMER_ETR_Polarity = TIMER_ETRPolarity_NonInverted; sTIM_CntInit.TIMER_BRK_Polarity = TIMER_BRKPolarity_NonInverted; TIMER_CntInit (MDR_TIMER1,&sTIM_CntInit); sTIM_ChnInit.TIMER_CH_Mode = TIMER_CH_MODE_PWM; sTIM_ChnInit.TIMER_CH_REF_Format = TIMER_CH_REF_Format6; sTIM_ChnInit.TIMER_CH_Number = TIMER_CHANNEL1; TIMER_ChnInit(MDR_TIMER1, &sTIM_ChnInit); sTIM_ChnInit.TIMER_CH_Number = TIMER_CHANNEL2; TIMER_ChnInit(MDR_TIMER1, &sTIM_ChnInit); sTIM_ChnInit.TIMER_CH_Number = TIMER_CHANNEL3; TIMER_ChnInit(MDR_TIMER1, &sTIM_ChnInit); TIMER_SetChnCompare(MDR_TIMER1, TIMER_CHANNEL1, CCR1_Val); TIMER_SetChnCompare(MDR_TIMER1, TIMER_CHANNEL2, CCR2_Val); TIMER_SetChnCompare(MDR_TIMER1, TIMER_CHANNEL3, CCR3_Val); sTIM_ChnOutInit.TIMER_CH_DirOut_Polarity = TIMER_CHOPolarity_NonInverted; sTIM_ChnOutInit.TIMER_CH_DirOut_Source = TIMER_CH_OutSrc_REF; sTIM_ChnOutInit.TIMER_CH_DirOut_Mode = TIMER_CH_OutMode_Output; sTIM_ChnOutInit.TIMER_CH_NegOut_Polarity = TIMER_CHOPolarity_NonInverted; sTIM_ChnOutInit.TIMER_CH_NegOut_Source = TIMER_CH_OutSrc_REF; sTIM_ChnOutInit.TIMER_CH_NegOut_Mode = TIMER_CH_OutMode_Output; sTIM_ChnOutInit.TIMER_CH_Number = TIMER_CHANNEL1; TIMER_ChnOutInit(MDR_TIMER1, &sTIM_ChnOutInit); sTIM_ChnOutInit.TIMER_CH_Number = TIMER_CHANNEL2; TIMER_ChnOutInit(MDR_TIMER1, &sTIM_ChnOutInit); sTIM_ChnOutInit.TIMER_CH_Number = TIMER_CHANNEL3; TIMER_ChnOutInit(MDR_TIMER1, &sTIM_ChnOutInit); TIMER_BRGInit(MDR_TIMER1,TIMER_HCLKdiv1); TIMER_Cmd(MDR_TIMER1,ENABLE); while(1) { } } |