Добавил:
ivanov666
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:Микропроцессорные системы. Применение микроконтроллеров семейства AVR для управления внешними устройствами
.pdf
61
/**
* @brief Обращение к таймерам – только через этот метод!
*
* @return cSoftTimers&
*/
static cSoftTimers& instance();
private:
/**
* @brief Вызывается аппаратным прерыванием
*
* @return void
*/
friend void irq_1ms_static();
/**
* @brief список таймеров
*/
dscTimer m_Timers[maxTimers];
/**
* @brief Показывает, что обработчик выполняется.
*/
bool m_HandlerRunning;
/**
* @brief Вызывается каждую миллисекунду
*
* @return void
*/
void irq_1ms();
/**
* @brief Инициализация аппаратного таймера
*
* @return void
*/
void hwIrqInit();
};
#endif // CSOFTTIMERS_H
// Файл cSoftTimers.cpp
#include <avr/interrupt.h>

62
#include <avr/io.h>
#include "cSoftTimers.h"
cSoftTimers::cSoftTimers() {
m_HandlerRunning=false;
for( int8_t i=0; i<maxTimers; i++){
delTimer(i);
}
}
void cSoftTimers::irq_1ms() {
for(auto &i:m_Timers){
i.counter=(i.counter!=0)?(i.counter-1):0;
}
if(!m_HandlerRunning){
for(auto &i:m_Timers){
if((i.counter == 0) && (i.period !=0 ) && (i.proc) ){
m_HandlerRunning=true;
i.counter = i.period;
i.proc();
m_HandlerRunning=false;
}
}
}
}
cSoftTimers::idT cSoftTimers::addTimer ( uint16_t period, cSoft-
Timers::timerProc handler ) {
idT r(0);
if( period == 0 ){
return(-1);
}
for(auto &i:m_Timers){
if(i.period == 0){
i.counter = i.period = period;
i.proc = handler;
break;
}
r++;

63
}
if(r>=maxTimers){
return(-1);
}
return(r);
}
void cSoftTimers::delTimer ( cSoftTimers::idT id ) {
if((id<0)||(id>=maxTimers)){
return;
}
m_Timers[id]={};
}
void cSoftTimers::rstTimer ( cSoftTimers::idT id ){
if((id<0)||(id>=maxTimers)){
return;
}
m_Timers[id].counter = m_Timers[id].period;
}
void irq_1ms_static() {
cSoftTimers::instance().irq_1ms();
}
ISR ( TIMER0_COMP_vect, ISR_NOBLOCK ) {
irq_1ms_static();
}
// прерывания 1 миллисекунда
//
#if F_CPU == 1000000UL
#define T0PSC ((0<<CS02) | (1<<CS01) | (0<<CS00))
#define T0OCR (F_CPU/(8UL*1000UL))
//
#elif F_CPU == 2000000
#define T0PSC ((0<<CS02) | (1<<CS01) | (0<<CS00))
#define T0OCR (F_CPU/(8000UL))
//
#elif F_CPU == 8000000
#define T0PSC ((0<<CS02) | (1<<CS01) | (1<<CS00))

64
#define T0OCR (F_CPU/(64000UL))
#endif
void cSoftTimers::hwIrqInit(){
// Режим таймера 1
TCCR0A = T0PSC | /* prescaler = 8 */
(1 << WGM01) | (0 << WGM00) | /* CTC mode */
(0 << COM0A0) | (0 << COM0A0) | /* output not use */
(0 << FOC0A); /* Force not use */
OCR0A= T0OCR;
TIFR0= (1<<OCF0A);
TCNT0=0;
TIMSK0= (1<<OCF0A);
}
void cSoftTimers::start(){
hwIrqInit();
}
void cSoftTimers::stop(){
TIMSK0=0;
OCR0A=0;
}
static cSoftTimers softTimers;
cSoftTimers& cSoftTimers::instance(){
return(softTimers);
}

65
Приложение В. Исходные тексты программной реализации
циклических буферов ( CycloBuf.h и CycloBuf.cpp )
// CycloBuf.h
#ifndef CYCLOBUF_H
#define CYCLOBUF_H
#include <stdint.h>
/**
* @brief Циклический буфер (не более 255 байт)
*/
class CycloBuf{
public:
/**
* @brief Конструктор
*/
CycloBuf();
/**
* @brief Инициализировать буфер
*
* @param buffer – указатель на буфер
* @param size – размер буфера
* @return void
*/
void init(uint8_t* buffer, uint8_t size);
/**
* @brief – очистить буфер
*
* @return void
*/
void clear();
/**
* @brief – проверить, пуст ли буфер
*
* @return bool
*/
bool isEmpty();
/**
* @brief Поместить байт в буфер
*
* @param c – байт
* @return bool – true – символ помещен в буфер
*/
bool putByte(uint8_t c);

66
/**
* @brief Считать символ из буфера
*
* @param c – считываемый символ
* @return bool – true – символ считан из буфера
*/
bool getByte(uint8_t& c);
private:
/**
* @brief Указатель на буфер
*/
uint8_t* m_Buffer;
/**
* @brief Размер буфера
*/
uint8_t m_Size;
/**
* @brief Голова
*/
uint8_t m_Begin;
/**
* @brief Хвост
*/
uint8_t m_End;
};
#endif // CYCLOBUF_H
// CycloBuf.cpp
#include "CycloBuf.h"
CycloBuf::CycloBuf () {
m_Buffer=nullptr;
m_Size=0;
clear();
}
void CycloBuf::init ( uint8_t* buffer, uint8_t size ){
m_Buffer=buffer;
m_Size=size;
clear();
}

67
void CycloBuf::clear(){
m_Begin=m_End=0;
}
bool CycloBuf::isEmpty(){
if(m_Begin==m_End){
return(true);
}
return(false);
}
bool CycloBuf::putByte ( uint8_t c ){
uint8_t e=m_End+1;
if(e>=m_Size){
e=e-m_Size;
}
if(e==m_Begin){
return(false);
}
m_Buffer[ m_End ] = c;
m_End=e;
return(true);
}
bool CycloBuf::getByte ( uint8_t& c ){
if( m_Begin !=m_End ){
c = m_Buffer[ m_Begin++ ];
}
else{
return(false);
}
if(m_Begin>=m_Size){
m_Begin=m_Begin-m_Size;
}
return(true);
}

68
Приложение Г. Исходные тексты программной реализации
драйвера UART ( cUSART.h и cUSART.cpp )
// cUSART.h
#ifndef CUSART_H
#define CUSART_H
#include <stdint.h>
#include "CycloBuf.h"
class cUSART{
public:
/**
* @brief Конструктор
*/
cUSART();
/**
* @brief Установить Скорость
* @param baud – скорость (19200 и др)
* @return void
*/
void setBaud(uint16_t baud);
/**
* @brief Начать использование USART
* @return void
*/
void start();
/**
* @brief Запустить передачу символа
* @param c – символ
* @return uint8_t – 0 – символ не передан, 1 – символ передан
*/
uint8_t putc(char c);
/**
* @brief Запустить передачу строки
* @param s – строка
* @return uint8_t – сколько байт удалось засунуть в буфер
*/

69
uint8_t puts(const char* s);
/**
* @brief Запустить передачу вектора байт
* @param s – вектор
* @param size – размер вектора
* @return uint8_t – сколько байт удалось засунуть в буфер
*/
uint8_t put(const char* s, uint8_t size);
/**
* @brief Cчитать строку из буфера
* @param s – буфер для считывания строки
* @param size – размер буфера
* @return uint8_t – сколько байт реально считано
*/
uint8_t get(char* s, uint8_t size);
/**
* @brief Запустить передачу строки из PROGMEM
* @param s – строка
* @return uint8_t – сколько байт удалось засунуть в буфер
*/
uint8_t putsF(const char* s);
/**
* @brief Синглтон
* @return cUSART&
*/
static cUSART& instance();
private:
enum Constants{
// Скорость по умолчанию
defaultBaudRate = 19200,
// Бит приемника
bitRx = 0,
// Бит передатчика
bitTx = 1,
// Размеры буферов
bufSize=0x80
};
/**
* @brief Буфер передатчика

70
*/
uint8_t m_TxB[Constants::bufSize];
CycloBuf m_TxBuffer;
/**
* @brief Буфер Приемника
*/
uint8_t m_RxB[Constants::bufSize];
CycloBuf m_RxBuffer;
/**
* @brief Инициализация аппаратной части
* @return void
*/
void hwInit();
void rx_complete();
void tx_complete();
friend void static_rx_complete();
friend void static_tx_complete();
};
#endif // CUSART_H
// cUSART.cpp
#include "cUSART.h"
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
cUSART::cUSART(){
m_RxBuffer.init(m_RxB, sizeof(m_RxB));
m_TxBuffer.init(m_TxB, sizeof(m_TxB));
setBaud( Constants::defaultBaudRate );
}
void cUSART::setBaud ( uint16_t baud ){
uint32_t ub= ( (F_CPU >> 3)/baud)-1;
UBRR = (ub & 0xFFFF);
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]
