Главная » Статьи » Proton PICBasic |
Не буду описывать все устройство, так как оно является частью коммерческой разработки. В общем, устройство разработано. Итак, режим захвата, модуль CCP. Мы будем рассматривать модуль CCP1, так как в устройствах с двумя модулями они работают одинаково, за исключением небольшого нюанса. Об этом вы можете прочитать в приложении от Microchip на русском языке, которое находится в прикрепленном архиве с проектом. Во-первых, модуль CCP представляет собой 8-разрядный регистр управления CCP1CON, 16-разрядный рабочий регистр, состоящий из двух 8-разрядных регистров CCPR1L и CCPR1H, и непосредственно вывод CCP1, который может быть как входом, так и выходом, в зависимости от режима работы модуля. В режиме захвата, этот вывод настраивается на вход. Также модуль, в зависимости от режима работы может взаимодействовать либо с таймером TMR1, либо с таймером TMR2. В режиме захвата модуль взаимодействует с таймером TMR1. Смысл работы режима захвата в том, чтобы захватить значение TMR1 в момент прихода импульса. Самый простой вариант измерения периода заключается в подсчете количества импульсов известной длительности между, умещающимися между двумя фронтами одного измеряемого периода. Подсчет заключается в фиксировании текущего значения TMR1 в момент прихода импульса на вход CCP1. Попытаюсь изобразить на рисунке, как работает этот модуль в режиме захвата. Итак, TMR1 настраивается на тактирование от внутреннего источника. Если предделитель равен 1:1, то инкремент таймера при частоте кварцевого резонатора (или другого) 4 МГц, будет происходить каждую микросекунду. Соответственно, то, что насчитает таймер – будет количеством микросекунд. Нетрудно перевести в миллисекунды и секунды. На верхней диаграмме показана именно частота тактирования TMR1. Ниже изображен вход CCP, на который поступает измеряемый сигнал. Если мы настроим захват по каждому фронту на входе CCP, то каждый раз, как приходит импульс, содержимое таймера TMR1 будет переписываться в CCPR1 – иными словами, регистр CCPR1 будет захватывать содержимое таймера. Это показано на рисунке. Следует заметить, что на рисунке частота на входе CCP показана условно. При такой частоте программа слишком часто будет уходить в прерывания и Вы можете протестировать данную стратегию на небольшом симуляторе, который я сделал специально для этой статьи (для этого у вас должен быть установлен Flash player). В симуляторе вам придется установить биты, разрешающие прерывание при возникновении захвата, а также прерывание при переполнении таймера TMR1. В блоке 'Обработчик прерывания' вам придется самостоятельно сбрасывать флаги прерываний. Нажмите на знак вопроса, чтобы прочесть справку. Здесь рассмотрен случай, когда частота осциллятора намного больше, чем частота входного сигнала. И еще один момент. Технология Flash не позволяет обрабатывать слишком быстрые события, кроме того, чтобы увидеть изменения всех флагов и регистров, нужно замедлить скорость выполнения, что я и сделал. В данном симуляторе подразумевается, что используется кварц на 4 МГц. Следовательно 1 машинный цикл равен 1 мкС. Но в симуляторе за 1 мкС взята единица времени, равная 50 мС. Поэтому при отсутствии входной частоты и включенном таймере, ждать его переполнения нужно 65535*50/1000 = 3276,8 мС ~ 54 мин. А вот и сама программа. Внимательно читайте комментарии. '-------------------------- Описание проекта
--------------------------------- 'Проект : Применение модуля захвата для вычисления периода импульса 'Автор : Admin 'Версия : 1.0.0 от 08.12.2011 '-------------------------- Опции компилятора -------------------------------- Declare SHOW_SYSTEM_VARIABLES = OFF; ' При симуляции в Proteus не показывать внутренние
переменные Declare Reminders = OFF ' Выключить напоминания компилятора Declare Warnings = On ' Выключить предупреждения компилятора ;-------------------------- Общие
настройки------------------------------------ Device = 16F877A ' Используемый микроконтроллер Declare Xtal = 20 ' Частота осциллятора 20 МГц ' Чем выше частота, тем выше точность измерения '-------------------------- Конфигурация
программирования ---------------- Config CP_ALL, DEBUG_OFF, WRT_OFF, CPD_ON, LVP_OFF,
BODEN_OFF, PWRTE_ON, WDT_OFF, HS_OSC '-------------------------- Настройки портов
----------------------------- Declare All_Digital = On ' Установить все порты цифровыми входами/выходами Dim PERIOD As
Word ' Переменная для захвата значения периода Dim FREQUENCY As
Dword ' Переменная для расчета частоты Dim DigitDisp As
Byte ' Переменная для вывода текущей цифры в порт Dim i As
Byte ' Переменная-счетчик Dim j As
Byte ' Переменная-счетчик Symbol Number = 2 * 20000000/4 ' Постоянная величина - частота осциллятора деленная
на 4 ' и умноженная
на 2 (так как предделитель TMR1 = 1:8, ' а захват
производится по каждому 16 фронту) Symbol PortOut = PORTC ' Порт для сегментов '-------------------------- Регистры специального
назначения--------------- '-------------------------- INTCON
--------------------------------------- Symbol CCP1IE = PIE1.2 ' Бит
разрешения прерывания от модуля CCP Symbol PEIE = INTCON.6 ' Бит
разрешения прерывания от периферийных устройств Symbol GIE = INTCON.7 ' Бит глобального разрешения прерываний Symbol TIMER = TMR1L.Word ' 16-разрядная переменная TMR1 Symbol CAPTURE = PIR1.2 ' Флаг прерывания от модуля CCP '-------------------------- Начало
------------------------------------------- On_Interrupt GoTo Int_Label ' При возникновении
прерывания перейти на Int_label PORTA = %00000000 ' Обнулим PORTA PORTB = %00000000 ' PORTB PORTC = %00000000 ' PORTC PORTD = %11111111 ' Выключим катоды индикаторов PORTE = %000 ' PORTE TRISA = %00000000 ' Порт A - на выход TRISB = %00000000 ' Порт B - на выход TRISC = %00000100 ' Порт C - на выход, за исключением вывода CCP1 TRISD = %00000000 ' Порт D - управление анодами TRISE = %000 ' Порт E - на выход OPTION_REG = %00100111 ' Этот регистр нам не нужен INTCON = 0 ' Запретим все прерывания CCP1CON = %00000111 ' Модуль CCP - в режиме захвата по каждому
16-фронту T1CON = %00110001 ' Тактирование TMR1 от внутреннего источника
предделитель 1:8 TIMER = 0 FREQUENCY = 0 PERIOD = 0 CCP1IE = 1 PEIE = 1 GIE = 1 ' Разрешение глобального прерывания GoTo MainProgram
'-------------------------- Обратный
отсчет-------------------------- Int_Label: '-------------Захват
периода----------------------------- If CAPTURE = 1 Then ' Проверка флага прерывания PERIOD = TIMER ' Захват в переменную значения, которое
насчитал ' TMR1 с последнего
прерывания TIMER = 0 ' Обнуление TMR1, чтобы он опять считал с нуля CAPTURE = 0 ' Сброс флага прерывания EndIf
Context
Restore ' Возврат из обработчика прерывания ' с восстановлением
регистров W и Status '-------------------------- Главная программа
------------------------- MainProgram: '----------Расчет частоты----------------------------- If PERIOD > 0 Then ' Как мы помним из школы, на ноль делить нельзя FREQUENCY = Number/PERIOD ' Получаем
значение частоты - обратной функции от периода EndIf '-------------Отображение частоты--------------------- For i = 1 To 10 ' Для уменьшения "прыгания" значения частоты
запустим цикл, ' за время которого значение периода может изменяться ' Но частота у нас уже посчитана! PORTD = %11111110 ' Для индикаторов с ОК - включим нулевой разряд
индикатора For j = 0 To 7 ' И последовательно включая следующий разряд, DigitDisp = Dig FREQUENCY, j ' присваиваем переменной текущую позицию числа и GoSub Display ' выводим ее в текущий разряд индикатора PORTD = (PORTD << 1) + 1 ' Сдвигаем ноль, которым зажигается разряд влево, '
зажигая следующий разряд Next j Next i GoTo MainProgram '-----------------------Вывод значений на
дисплей----- Display: PortOut = LookUpL DigitDisp,[$EB,$21,$BA,$B3,$71,$D3,$DB,$A1,$FB,$F3] ' Значения сегментов вычислялись с помощью ' этого инструмента, так как сегменты идут непоследовательно DelayMS 2 ' Задержка для видимости отображения PortOut = 0 ' Гасим сегменты для устранения послесвечения Return ' Возврат End Скачать архив с материалами статьи можно здесь | ||
Просмотров: 17594 | Комментарии: 8 | | |
Всего комментариев: 8 | |||||||
| |||||||