Содержание
1. Автоматизация поиска информации
в сети интернет. Занятие 5.
При работе с интернетом периодически приходится сталкиваться с проблемами, когда страница недоступна или загружается долго. Поэтому в программе необходимо вводить максимальное время ожидания, по прошествии которого переходить, например, на другую страницу или делать еще какие-нибудь действия.
Для этого в программу нужно добавить таймер. Делается это следующим образом.
…
Результат работы программы в окне отладки:
время ожидания - '1', сек
время ожидания - '2', сек
время ожидания - '3', сек
время ожидания - '4', сек
время ожидания - '5', сек
время ожидания - '6', сек
время ожидания - '7', сек
время ожидания - '8', сек
время ожидания - '9', сек
время ожидания - '10', сек
Таймаут!
страница загружена - первая
…
2. Программирование на языке С на примере микроконтроллера ATmega168. Программный RTC и
будильники.
В выпуске журнала №12 (статья 5) был рассмотрен пример использования внешней микросхемы RTC. RTC можно сделать и программно, если такая реализация подходит для реализации проекта (аппаратный RTC в большинстве случаев работает более точно, потребляет меньше энергии, но стоимость такого решения больше).
Для реализации программного RTC запрограммируем таймер 2 на срабатывание каждую миллисекунду. Добавим переменные для секунд, минут и часов. В обработке прерывания таймера 2 будем вести подсчет миллисекунд и каждую секунду изменять переменную секунд и при необходимости изменять переменную минут и часов. В основном цикле программы будем выводить текущее время по UART в терминальную программу.
Программа написана для среды разработки ATMEL Studio® [1].
Текст программы:
//
// Часы реального времени (RTC).
программная реализация
//
#include <avr/io.h> // описание регистров микроконтроллера
#define F_CPU 16000000L // задали частоту микроконтроллера
#include <util/delay.h> // подключаем функции задержки
#include <avr/interrupt.h> // подключим библиотеку для работы с прерываниями
#include <stdio.h> // библиотека
стандартного ввода-вывода
#include <avr/pgmspace.h> // библиотека для работы с Flash
памятью программ
// функция передачи байта
void UART_TX_byte(char tx_data) // передаваемый байт
{
while(!(UCSR0A & (1<<UDRE0))) {} // ожидаем окончания
передачи
UDR0 = tx_data; // начало передачи
данных
}
// функция передачи строки
void UART_TX_string(char * str) // указатель на строку
{
while((*str)
!= 0x00) // проверка на окончание строки
{
UART_TX_byte(*(str++)); // передаем текущий байт и увеличиваем
указатель (на следующий элемент)
}
}
char msg[100];
// Программный таймер RTC
#define msec_cnt_top 1000 // значение счета (мс) - 1 сек
volatile unsigned int msec_cnt = 0; // счетчик таймера (мс)
volatile unsigned int sec = 0; // секунды
volatile unsigned int min = 0; // минуты
volatile unsigned int hour = 0; // часы
// главная функция
int main(void)
{
// настройка UART
UCSR0B |= (1<<TXEN0); // разрешим передачу данных
// при сбросе установлено
// UMSEL == 00 - асинхронный
режим
// UPM = 00 - без паритета
// USBS = 0 - 1 стоп бит
// UCSZ = 011 - 8 бит данные
// 8N1 - 8 бит, без паритета,
1 стоп-бит
UBRR0 = 16; // скорость 57600 при
16000000 и U2X = 0
// счетчик времени на таймере
2
// время срабатывания - 1 мс
// 16000000/64/1000 = 250 -
значение сравнения
// режим CTC (2)
TCCR2A |= (1<<WGM21);
TCCR2B |= (1<<CS22); // делитель на 64
OCR2A = 250-1;
TIMSK2 |= (1<<OCIE2A); // разрешим прерывание при сравнении по каналу А
sei(); // разрешим прерывания глобально
// начальная установка
времени
sec = 55;
min = 59;
hour = 12;
UART_TX_string("\r\nRTC:\r\n");
// основной цикл программы
while(1)
{
// вывод текущего времени по
UART
//sprintf_P(msg,PSTR("%d:%d:%d\r\n"),
hour, min, sec);
//sprintf_P(msg,PSTR("%2d:%2d:%2d\r\n"),
hour, min, sec);
sprintf_P(msg,PSTR("%2.2d:%2.2d:%2.2d\r\n"), hour, min, sec);
UART_TX_string(msg);
_delay_ms(1000); // задержка 1 сек
}
}
// обработка прерывания таймера 2 при сравнении по каналу А
ISR(TIMER2_COMPA_vect)
{
if(msec_cnt < msec_cnt_top) msec_cnt++; // счетчик миллисекунд -
увеличиваем
else
{
msec_cnt = 0; // сбрасываем счетчик
миллисекунд
if(sec < 59) sec++; // увеличиваем секунды
else
{
sec = 0; // сбрасываем секунды
if(min < 59) min++; // увеличиваем минуты
else
{
min = 0; // сбрасываем минуты
if(hour < 23) hour++; // увеличиваем часы
else
{
hour = 0; // сбрасываем часы
}
}
}
}
}
Результат работы программы:
RTC:
12:59:55
12:59:56
12:59:57
12:59:58
12:59:59
13:00:00
13:00:01
13:00:02
13:00:03
…
В следующем примере добавим будильник. Для этого сделаем переменные для хранения времени срабатывания будильника и будем проверять их в функции обработки прерывания (изменения выделены серым). Заметим, что проверяются также и миллисекунды. Это позволяет избежать двойного срабатывания будильника в течение одной секунды.
…
В третьем примере добавим второй будильник, который будет через каждые 10 секунд переключать светодиод.
…
3. Программирование для ПЛИС на языке VHDL на примере EP4CE10А17С8N. Делитель
частоты.
В качестве макета будет использоваться КИТ «OPENEP4CE10-C-PACKAGE-B» [1]. Программы будут разрабатываться в среде «Quartus ® II» [2].
Для начала рассмотрим простой пример, в котором сделаем делитель частоты, на вход которого будет подаваться тактовая частота «clk» для ПЛИС, а к выходу будет подключен светодиод. Пусть необходимо сформировать частоту 1 Гц для мигания светодиода.
Подключение тактового сигнала и светодиодов на плате «CoreEP4CE10» КИТа следующее:
CLK – E16
LED-R1 –
D12
LED-R2 –
C11
LED-R3 –
B10
LED-R4 – B7
Эта информация понадобится при назначении выводов ПЛИС.
Текст программы:
--
-- делитель с выходом на светодиод
--
-- подключение библиотек
library IEEE; -- библиотека ieee
use IEEE.std_logic_1164.all; -- основные типы VHDL (std_logic)
use IEEE.std_logic_unsigned.all; -- беззнаковая
арифметика, функции преобразования, сравнения
use IEEE.std_logic_arith.all; -- библиотека арифметических
операций
-- объявление "сущности"
объекта (описание сигналов для связи с внешними устройствами)
-- Тактовая частота – 50 МГц
-- Чтобы получить 1 Гц, нужно
поделить на 50000000
--
Требуемая разрядность счетчика - 26 (2^26 = 67108864)
entity Divider_LED is
generic
(N: natural := 26; -- разрядность счетчика
Div: natural := 50000000); -- значение
делителя
port
(
clk : in std_logic;
-- вход
clk_out :
out std_logic -- выход
);
end Divider_LED;
…
Назначение выводов ПЛИС (Меню «Assignments->Pin Planner»):
«»
[2].
После компиляции и загрузки программы наблюдайте мигание светодиода L4 на плате.
«»
[1].
Список литературы и
ссылки
1.
«OPENEP4CE10-C-PACKAGE-B». © Waveshare Electronics.
2.
«Quartus ® II». © «Altera Corporation».
4. Программа разработки и анализа
ТЗ «176». Часть 1.
Для многих разработчиков - фрилансеров актуален вопрос «как не ошибиться при согласии на выполнение определенной работы?». Чтобы при окончании работы вас не мучала мысль «лучше бы я вообще за эту работу не брался». Или хотя бы снизить вероятность такого негативного результата. На рынке можно найти много работ с низкой оплатой, непонятными требованиями заказчика и т.п. Нужно ли за них браться?
Попробуем решить эту задачу и сделать программу для компьютера, которая поможет не упустить ключевые моменты и помочь обработать исходные данные.
В общем здесь видится 3 объекта – разработчик (вы), заказчик и предмет работы.
Начнем с «себя любимого».
…
Так это будет в программе:
«
»
[1].
…
5. Программирование на языке С на примере микроконтроллера STM32F407VGT6. Кнопка с
анализом «короткого» и «долгого» нажатия.
Некоторые примеры работы с
кнопками уже были рассмотрены в журнале №12 (статья 2). Однако есть еще много
разных вариантов работы с кнопками. Макет можно собрать на плате «STM32F4DISCOVERY» [5], плате «163»
и дополнительной кнопке (на плате «STM32F4DISCOVERY» есть только одна
пользовательская кнопка). Вместо платы «163»
можно использовать любой модуль «USB-UART».
Пример программ будет даваться для компилятора «CooCox®» [4].
Рассмотрим
задачу для димера (управление яркостью светодиода) с помощью
двух кнопок. При «коротком» нажатии на кнопки яркость будет
увеличиваться/уменьшаться на один «дискрет яркости».
При длительном удержании кнопки – включаться на полную яркость или выключаться.
Для увеличения яркости будет использоваться кнопка B1, расположенная на плате. Для уменьшения – дополнительная, подключенная к «3V» и порту PA1.
Текст основной программы (все файлы исходного кода вы можете найти в приложении):
// Работа с кнопками.
// Пример 5. Кнопка с анализом «короткого» и «долгого»
нажатия. Димер.
//
#include "stm32F4xx.h" // описание периферии
#include "stdio.h" // описание стандартных
функций
#include "string.h" // описание функций работы
со строками
// определения частот шин микроконтроллера
#define APB1_CLOCK 16000000L // частота шины APB1
#include "UART3_drv.h" // объявления функций для
работы с USART3
char msg[200];
// массив для
формирования сообщений для вывода по UART
// состояние кнопки
#define key_state_off 0 // не нажата
#define key_state_bounce 1 // дребезг
#define key_state_on_short 2 // нажата "короткое"
#define key_state_on_long 3 // нажата "длинное"
volatile unsigned char key_state = key_state_off; // состояние кнопки 1
volatile unsigned char
key_state_2 = key_state_off; // состояние кнопки 2
// счетчик времени дребезга
#define key_bounce_time_cnt_top 50 // время дребезга в мс
volatile unsigned int key_bounce_time_cnt; // счетчик времени дребезга в мс
volatile unsigned int key_bounce_time_cnt_2; // счетчик времени дребезга в мс 2
// 0 - не нажата
// 1 - кнопка нажата (интервал дребезга пройден),
короткое нажатие
//
2 - кнопка нажата, длинное нажатие
volatile unsigned char key_press_flag = 0;
volatile unsigned char
key_press_flag_2 = 0;
// счетчик времени длительного нажатия
#define key_long_press_time_cnt_top
2000 // время
"длинного" нажатия в мс
volatile unsigned int key_long_press_time_cnt; // счетчик времени "длинного" нажатия в мс
volatile unsigned int key_long_press_time_cnt_2; // счетчик времени "длинного" нажатия в мс
…
6. Программирование на языке С на примере микроконтроллера STM32F407VGT6. Кнопка с
анализом с анализом «длительности нажатия". Изменение параметра в широких
пределах.
Если необходимо устанавливать какой-либо параметр (например, громкость, позицию, частоту и т.п.) в широком диапазоне, но с большой точностью и быстро, можно сделать логарифмическое изменение параметра при длительном удержании кнопки, т.е. чем дольше кнопка удерживается, тем большее изменение параметра производится. Рассмотрим пример такой программы. В ней будет использовано 3 шага приращения значения, а также работает автоповтор нажатия кнопки.
Пример программы будет даваться для компилятора «CooCox®» [4]. Назначение и подключение кнопок - как в предыдущей статье.
Текст основной программы (все файлы исходного кода вы можете найти в приложении):
// Работа с кнопками.
// Пример 6. Кнопка с анализом «длительности
нажатия". Изменение параметра в широких пределах.
//
#include "stm32F4xx.h" // описание периферии
#include "stdio.h" // описание стандартных
функций
#include "string.h" // описание функций работы
со строками
// определения частот шин микроконтроллера
#define APB1_CLOCK 16000000L // частота шины APB1
#include "UART3_drv.h" // объявления функций для
работы с USART3
char msg[200];
// массив для
формирования сообщений для вывода по UART
// состояние кнопки
#define key_state_off 0 // не нажата
#define key_state_bounce 1 // дребезг
#define key_state_on_short 2 // нажата, "короткое" +-1
#define key_state_on_long_plus_minus10 3 // нажата, "длинное" +-10
#define key_state_on_long_plus_minus100 4 // нажата, "длинное" +-100
volatile unsigned char key_state = key_state_off; // состояние кнопки 1
volatile unsigned char
key_state_2 = key_state_off; // состояние кнопки 2
// счетчик времени дребезга
#define key_bounce_time_cnt_top 50 // время дребезга в мс
volatile unsigned int key_bounce_time_cnt; // счетчик времени дребезга в мс
volatile unsigned int key_bounce_time_cnt_2; // счетчик времени дребезга в мс 2
// 0 - не нажата
// 1 - кнопка нажата (интервал дребезга пройден),
короткое нажатие +-1
// 2 - кнопка нажата (интервал дребезга пройден),
длинное нажатие +-10
// 3 - кнопка нажата (интервал дребезга пройден),
длинное нажатие +-100
volatile unsigned char key_press_flag = 0;
volatile unsigned char
key_press_flag_2 = 0;
// счетчик временни автоповтора
#define key_repeat_time_cnt_top 500 // время автоповтора в мс
volatile unsigned int key_repeat_time_cnt; // счетчик времени автоповтора
volatile unsigned int key_repeat_time_cnt_2; // счетчик времени автоповтора 2
// счетчик времени длительного нажатия
#define key_long_press_time_cnt_top_plus_minus10 2500 // время "длинного" нажатия +-10 в мс
#define key_long_press_time_cnt_top_plus_minus100 4500 // время "длинного" нажатия +-100 в мс
volatile unsigned int key_long_press_time_cnt; // счетчик времени "длинного" нажатия в мс
volatile unsigned int key_long_press_time_cnt_2; // счетчик времени "длинного" нажатия в мс
unsigned int parametr;
…
Результат работы программы (в терминальной программе):
Test key short-long-3_levels:
… здесь нажали и удерживаем первую кнопку
parametr - 1
parametr - 2
parametr - 3
parametr - 4
parametr - 5
parametr - 15
parametr - 25
parametr - 35
parametr - 45
parametr - 55
parametr - 155
parametr - 255
parametr - 355
parametr - 455
parametr - 555
parametr - 655
parametr - 755
parametr - 855
parametr - 955
parametr – 1055
… здесь нажали и удерживаем вторую кнопку
parametr - 1054
parametr - 1053
parametr - 1052
parametr - 1051
parametr - 1050
parametr - 1040
parametr - 1030
parametr - 1020
parametr - 1010
parametr - 1000
parametr - 900
parametr - 800
parametr - 700
parametr - 600
parametr - 500
parametr - 400
parametr - 300
В данной программе отсутствует проверка на ограничения параметра сверху и снизу, т.е. параметр будет изменяться «по кругу».
7. Программирование на языке С++ на примере микроконтроллера ATmega328. Мигание
светодиодом определенное число раз.
Задача «мигнуть» несколько раз светодиодом достаточно часто встречается при создании различных устройств. Рассмотрим пример программы, который позволяет задавать количество «миганий», длительность свечения светодиода и паузы. Использование прерываний аппаратного таймера микроконтроллера делает программу эффективно работающей.
Пример программы (скетча) приведен для «Arduino IDE» [2].
Для компиляции скетча необходимо подключить следующие библиотеки:
«MsTimer2.h».
…
// зададим параметры мигания
Led_state_on_time = 500; // время свечения
светодиода, мс
Led_state_off_time = 500; // время паузы, мс
Led_blinks_times = 6;
// количество миганий светодиода
…
8. Программирование на языке С на примере микроконтроллера STM32F407VGT6. Работа с UART.
Прием данных. Анализ аппаратных флагов ошибок.
Несколько примеров приема данных по UART были рассмотрены в журнале №16 (статья 1). В данной статье рассматривается пример анализа аппаратных флагов ошибок. Встроенный в микроконтроллер UART способен определять следующие ошибки при приеме:
- перезапись принятых данных (если принятый байт не был считан до прихода следующего байта, соответственно он теряется)
- ошибка кадра
- ошибка паритета
- наличие «шума»
Во всех этих случаях прием данных может быть неправильным, поэтому необходимо анализировать соответствующие флаги в программе. Флаги находятся в регистре «SR». При считывании регистра «SR» и «DR» флаги сбрасываются, поэтому для их последующего анализа сделаем копирование регистра «SR» во вспомогательную переменную.
Пример программы будет даваться для компилятора «CooCox®» [4].
…
9. Программирование на языке С на примере микроконтроллера STM32F407VGT6. Работа с UART.
Прием данных. Синтаксический анализ данных (парсинг).
Синтаксический анализ входных данных требуется при работе с различными коммуникационными устройствами, чтобы выделить определенные данные для последующей их обработки. Рассмотрим пример программы управления светодиодами. Команда будет состоять из трех полей, разделенных символом ‘_’. В первом поле будет присутствовать слово «led», во втором – номер светодиода, в третьем – операция включения или выключения.
Для написания синтаксического анализатора наиболее подходит строковая функция «strtok» [15]. Она позволяет выделить в тексте лексемы, ограниченные заданными разделителями. Разделители могут быть разными.
Для возможности набирать команды в любом регистре, используется функция перевода строки в нижний регистр «tolower» [15].
Для сравнения выделенных лексем с нужными используем функцию сравнения строк «strncmp» [15].
После получения лексем производится их анализ и если они ошибочны, выводятся соответствующие сообщения.
…
Результат работы программы (в терминальной программе). Команды выделены черным, ответ - зеленым:
UART_RX_INT_Parser:
led_1_on
device_name - led
device_num - 1
device_funk - on
lED_2_ON
device_name - led
device_num - 2
device_funk - on
led_3_ON
device_name - led
device_num - 3
device_funk - on
led_4_on
device_name - led
device_num - 4
device_funk - on
lef_1_on
device_name - lef
device_num - 1
device_funk - on
Error 1
…
10. Примеры программ на С++ для персональных компьютеров.
Рассмотрим
пример создания приложения - терминальной программы для RS232/485, Назовем приложение, например
«Terminal_232_485». Тип приложения выберем на основе диалоговых окон.
Работа с COM портом подробно была освещена в журнале №6
(статья 7) и №20 (статья 4).
В тех примерах программ использовались фиксированные настройки порта, которые пользователь не мог изменить. Сейчас сделаем их изменяемыми пользователем.
…
Общий вид окна программы:
«»
[1]
Продолжение следует.