В начало | Зарегистрироваться | Заказать наши киты почтой
 
 
 
 

Несколько функций для програмной реализации протокола I2C на AVR

📆7 февраля 2015   ✒️teXnik   🔎20.143   💬22  
Несколько функций для  програмной реализации протокола I2C на AVRДобрый день, дорогие друзья! Решил поделиться с вами несколькими функция для работы по протоколу I2C на микроконтроллерах AVR. Функции реализуют программную работу с протоколом в режиме Master.

Писал я прошивку для управления звуковым процессором. Писал в CodeVision и никаких проблем не было. Но пришлось пересесть на IAR, в котором не нашлось библиотек для программной реализации I2C.
Попытки запустить библиотеки, найденные на просторах Интернета, успеха не принесли и решил я написать необходимый минимум сам.

Содержание статьи / Table Of Contents

Протокол I2C

I2C — последовательная шина данных для связи интегральных схем, использующая две двунаправленные линии связи (SDA и SCL). Используется для соединения низкоскоростных периферийных компонентов с материнской платой, встраиваемыми системами и мобильными телефонами.
Для начала нам понадобиться много #define'ов

///i2c port 
#define i2c_time 10 // пауза в микросекундах (4 паузы на такт передачи)
#define i2c_port PORTB 	
#define i2c_ddr DDRB	
#define i2c_pin PINB
#define sda 2	       // номера выводов соответствующего порта
#define scl 3	
// управление битами при записи
#define clrsda i2c_port &= ~(1 < < sda)  
#define setsda i2c_port |= (1 < < sda)
#define clrscl i2c_port &= ~(1 < < scl)
#define setscl i2c_port |= (1 < < scl) 
// управление битами при чтении
#define rxscl i2c_ddr &= ~(1 < < scl) 
#define txscl i2c_ddr |= (1 < < scl) 
#define txsda i2c_ddr |= (1 < < sda)
#define rxsda i2c_ddr &= ~(1 < < sda) 

#define i2c_readstatus (1 < < sda)


Для работы потребуется функция осуществляющую задержку. Если вы используете IAR то её объявление выглядит так:

#ifndef DELAY_H
#define DELAY_H
#endif
#define CPU_CLK 8000000 //частота на которой работает контроллер
#define delay_us(u) __delay_cycles((CPU_CLK/1000000)*u)
#define delay_ms(m) __delay_cycles((CPU_CLK/1000)*m)


Функции

Передачу инициирует ведущее устройство, формируя состояние СТАРТ на шине. С этой функции я и начал.
void i2c_start(void)
{
asm("cli");
  txsda;       
  clrsda;
  delay_us(i2c_time);
  txscl;
  clrscl;
  delay_us(i2c_time);
asm("sei");
};

Функция ничего не возвращает, и на время своего выполнения запрещает все прерывания.
Окончание передачи также инициирует ведущее устройство формируя состояние СТОП на шине.

void i2c_stop(void)          
{
asm("cli");  
  txsda;
  clrsda;
  delay_us(i2c_time);
  rxscl;
  delay_us(i2c_time);
  rxsda;
asm("sei");
};


Передача одного байта данных:
char i2c_tx(char data)
{
asm("cli");
char x;
char b=1;
  for(x=8; x; x--)  // цикл на 8 передаваемых бит
  {
    if((data&0x80)==0)  // проверяем старший бит в передаваемом байте
    {
      txsda; // выдаем бит данных на SDA
      clrsda;
    }
    else
    {
      rxsda; // или оставляем линию в покое
    };
    txscl; // выдаем такт в линию SCL
    clrscl;
    delay_us(i2c_time);
    data < < = 1; // сдвигаем передаваемые биты влево
    rxscl;
    delay_us(i2c_time< < 1);
    txscl;
    clrscl;
    delay_us(i2c_time);
  };
  rxscl;
  delay_us(i2c_time);
  rxsda;
  if ((i2c_pin & i2c_readstatus)==i2c_readstatus)                      
  { 
    b=0;
  };    // считываем возможный ACK бит 
  delay_us(i2c_time); 
  txscl;
  clrscl;
  delay_us(i2c_time< < 1);
asm("sei");
  return b;
};

Функция возвращает 1, если slave подтвердил передачу и 0 если не подтвердил.

Чтение байта:
Передаем в качестве параметра ack единицу, если хотим, чтобы наш master дал подтверждение и любое другое число, чтобы ответить NACK.

char i2c_rx(char ack)
{
asm("cli");
char x; // счетчик
char data=0; // принимаемый байт 
  rxsda; // настраиваем sda на чтение
  for(x=0; x< 8; x++) // цикл приема бит
  {
    txscl;// выдаем такт на SCL
    clrscl;
    delay_us(i2c_time);
    rxscl;
    delay_us(i2c_time);
    if ((i2c_pin & i2c_readstatus)==i2c_readstatus) // считываем из порта              
    { 
      setb((7-x),data); // если считали единицу - устанавливаем соответствующий бит
    };
    delay_us(i2c_time);
    txscl;
    clrscl;
    delay_us(i2c_time);
  };
if(ack==1)  //выдаем или не выдаем ACK на шину
    {
      txsda;
      clrsda;
    }
    else
    {
      rxsda;
    };
    txscl;
    clrscl;
    delay_us(i2c_time);
    rxscl;
    delay_us(i2c_time< < 1);
    txscl;
    clrscl;
    delay_us(i2c_time);
asm("sei");
  return data;
};


Пример

Типичная передача данных по протоколу I2C выглядит следующим образом:
  1. СТАРТ
  2. Адрес+бит чтение/запись
  3. Чтение/Запись
  4. xxx
  5. Стоп


В качестве примера приведу функцию записи в аудио процессор tda7439.

void loadtoTDA(void)
{
char p;
i2c_start();
i2c_tx(0x88);// адрес тда
i2c_tx(0x10); // режим записи в тда - инкрементный
for (p=0;p< 8;p++)
    {
    i2c_tx(param[p]); // передаем массив с параметрами для тда
    };  
i2c_stop();    
};


Это минимум функций необходимый для работы мастера на шине. Все функции проверены и протестированы, как в симуляторе так и в "железе".
Надеюсь, они будут полезны не только мне, но и вам.
Спасибо за внимание!

Камрад, рассмотри датагорские рекомендации

🌼 Полезные и проверенные железяки, можно брать

Опробовано в лаборатории редакции или читателями.




 

Читательское голосование

Нравится

Статью одобрил 61 читатель.

Для участия в голосовании зарегистрируйтесь и войдите на сайт с вашими логином и паролем.
 

Поделись с друзьями!

 

 

Связанные материалы

 

Схема на Датагоре. Новая статья Программная реализация протокола I2C на AVR в CodeVisionAVR... Пару лет назад, изучая Atmega8, я захотел программно реализовать работу с устройствами на шине...
Схема на Датагоре. Новая статья Программная реализация протокола SPI на AVR в CodeVisionAVR... Всем коллегам и согражданам привет! Увлёкся я изучением протоколов. Про реализацию протокола I2C у...
Схема на Датагоре. Новая статья Использование МК ATMega163, ATMega163L, ATMega16 в Arduino IDE... Популярная среда разработки Arduino IDE привлекает большим количеством готовых библиотек и...
Схема на Датагоре. Новая статья Беспроводной канал связи 2,4 ГГц на базе трансивера nRF24L01+ от Nordic Semiconductor. Часть 2... Продолжаем разговор. Как-то раз мы с пацанами решили соединить Микроконтроллер Attiny85 на Али...
Схема на Датагоре. Новая статья Arduino shield: акселерометр на LIS302DL... Собрал недавно arduino на atmega8, поморгал диодом, захотелось большего. Начал изучать различные...
Схема на Датагоре. Новая статья Таймер от 1 секунды до 100 часов на микроконтроллере ATMEL AT89C2051... Картинка от Novelty Kitchen Timers В радиолюбительской практике частенько необходим таймер:...
Схема на Датагоре. Новая статья Беспроводной канал связи 2,4 ГГц на базе трансивера nRF24L01+ от Nordic Semiconductor. Часть 1... Доброго вам дня, уважаемые граждане и гости Датагор.ру - этого замечательного сообщества увлечённых...
Схема на Датагоре. Новая статья Грызём микроконтроллеры. Урок 2. CodeVision и С... Предлагаю продолжить изучение микроконтроллеров… Второй урок будет посвящен по большей части...
Схема на Датагоре. Новая статья Визуализация для микроконтроллера. Часть 2. TFT дисплей 1.8" (128х160) на ST7735... Следующий из рассматриваемых нами модулей обладает полноцветным дисплеем под управлением...
Схема на Датагоре. Новая статья Визуализация для микроконтроллера. Часть 3. TFT дисплей 2.8" (240х320) на ILI9341... Битва за урожай закончена, можно продолжить повествование. Полноцветный TFT-дисплей 240×320 ILI9341...
Схема на Датагоре. Новая статья Немного про шину 1-Wire и цифровой термометр DS18b20... Здравствуйте, друзья. Хочу предложить вашему вниманию несколько простых функций для работы с шиной...
Схема на Датагоре. Новая статья Грызём микроконтроллеры. Урок 8. Программирование кнопок, клавиатуры, энкодера... Здравствуйте, дорогие Датагорцы! По некоторым слабо зависящим от меня причинам не мог участвовать в...
 

Комментарии, вопросы, ответы, дополнения, отзывы

 

Назад Вперед
<
Читатель Датагора

vladimirm2

<
Читатель Датагора

teXnik

<
Читатель Датагора

demiurg1978

<
Читатель Датагора

teXnik

<
Читатель Датагора

andrdoy

<
Читатель Датагора

Sergiy_83

<
Читатель Датагора

teXnik

<
Читатель Датагора

demiurg1978

<
Читатель Датагора

teXnik

<
Читатель Датагора

mk85

<
Читатель Датагора

AudioKiller

<
Читатель Датагора

Datagor

<
Читатель Датагора

Sergiy_83

<
Читатель Датагора

teXnik

<
Читатель Датагора

AudioKiller

<
Читатель Датагора

12val12

Назад Вперед

Добавить комментарий, вопрос, отзыв 💬

Камрады, будьте дружелюбны, соблюдайте правила!

  • Смайлы и люди
    Животные и природа
    Еда и напитки
    Активность
    Путешествия и места
    Предметы
    Символы
    Флаги
 
 
В начало | Зарегистрироваться | Заказать наши киты почтой