Форум Микро-Чип
Поиск и заказ электронных компонентов
 

Вернуться   Форум Микро-Чип > Вопросы начинающих

Вопросы начинающих Прежде чем задать вопрос, стоит воспользоваться поиском

Ответ
 
Опции темы Опции просмотра
Старый 02.11.2015, 23:24   #1
CocuckuH
Member
 
Регистрация: 27.05.2015
Возраст: 27
Сообщений: 32
Вес репутации: 100/10
CocuckuH will become famous soon enoughCocuckuH will become famous soon enough
По умолчанию Не могу запустить аппаратный I2C на PIC18F258

Здравствуйте.

Уже битый месяц пытаюсь запустить обмен с дисплеем по шине i2c.

Сначала в функции I2C_check даже бит RW не изменялся и МК уходил в бесконечный цикл, но путём долги копаний в даташите и ковыряний в коде, удалось добиться небольшого прогресса.

Сейчас I2C_check успешно выполняется, но флаг прерывания SSPIF не поднимается и МК в цикле ожидает его... Соответственно, в функции I2C_LCD_init дальше I2C_start() ничего не идёт.

Вот код (простите за объём, это реализация I2C):

Код:
#include <pic18.h>

//------------------------------------------------------
//   PIC18F258
//------------------------------------------------------
__CONFIG(1, XT & OSCSDIS); 
__CONFIG(2, BOREN & BORV27 & PWRTEN & WDTDIS); 

__CONFIG(4, DEBUGEN & LVPDIS & STVRDIS); 
__CONFIG(5, UNPROTECT);
__CONFIG(6, WPU);
__CONFIG(7, PTBRU); 

#define MAIN_FREQ 4000 // кГц - частота контроллера
#define I2C_FREQ 100   // кГц - частота обмена по I2C
#define SCL_PIN RC3
#define SDA_PIN RC4
#define SCL_TRIS TRISC3
#define SDA_TRIS TRISC4

#define I2C_GEN_MASTER (((MAIN_FREQ/I2C_FREQ) / 4) - 1)
// При установке битов SSPM3-SSPM0 регистра SSPSTAT в 1000, модуль I2C будет
// работать в Master Mode, а частота тактового сигнала I2C рассчитывается по формуле:
// i2c_frq = main_frq / (4*(SSPADD+1))
// поэтому расчет коэф генератора нужно вести по "обратной" формуле.

// Мигаем диодом (у меня диод на RB2). mode - длительность периода, 1\0 - длинный\короткий
void doPEEK(unsigned char mode) {
     TRISB2=0; // устанавливаем порт на выход
     LATB2=1; // зажигаем диод
     if (mode) { _delay(90000); }   
     _delay(10000);
     LATB2=0; // гасим диод
     if (mode) { _delay(90000); }   
     _delay(10000);  }

//-------------------------------------------------------------------------------------
     
// Реализация аппаратного I2c на PIC

// Формирование служебных последовательностей СТАРТ, СТОП и ПОВТОРНЫЙ СТАРТ
// производится установкой в 1 соответствующих битов в регистре SSPCON2.
// Контролировать окончание процесса будем по биту чтения\записи - RW.
// В режиме Slave - 1=Read, 0=Write.
// В режиме Master - 1=Transmit in progress, 0=Transmit is not in progress.

void I2C_check(unsigned char mode) {
     // mode=1 - master, mode=0 - slave.
     // Проверка освобождения шины. Если выполняется передача данных - бит RW=1
     if (mode) { while (RW) { }; }
     // простой, если хотя бы один из первых пяти битов SSPCON2 !ноль
     // вторым циклом проверяем, что биты SEN, RSEN, PEN, RCEN, ACKEN
     // сброшены и модуль MSSP не используется.
     while (SSPCON2 & 0x1F) { }; }

void I2C_start(void) {// СТАРТ последовательность
   I2C_check(1);       // проверка освобождения шины
   SSPIF = 0;          // обнуляем прерывание
   SEN = 1;            // сформировать СТАРТ
   while (!SSPIF);    // ожидание завершения
   doPEEK(1);          // Мигнём, если флаг поднимется
   SSPIF = 0; }

void I2C_restart(void) {// Повторный СТАРТ
   I2C_check(1);         // проверка освобождения шины
   SSPIF = 0;               // обнуляем прерывание
   RSEN = 1;             // сформировать П.СТАРТ
   while(!SSPIF);       // ожидание завершения
   SSPIF = 0;    }

void I2C_stop(void) { // СТОП последовательность
   I2C_check(1);       // проверка освобождения шины
   SSPIF = 0;             // обнуляем прерывание
   PEN = 1;            // сформировать СТОП
   while(!SSPIF);     // ожидание завершения
   SSPIF = 0;    }

// Для того чтобы передать данные их просто нужно записать в регистр SSPBUF.
void I2C_sendbyte(unsigned char data, unsigned char mode) {
   I2C_check(mode);       // проверка освобождения шины
   SSPIF = 0;                // обнуляем прерывание
   SSPBUF = data;         // послать данные
   while(!SSPIF);        // ожидание завершения
   SSPIF = 0;
   while (ACKSTAT) { }; }// проверка подтверждения приема
// ACKSTAT - бит подтверждения приёма ведомым (Master Transmit only);
// ACKSTAT=1 подтверждения нет, ACKSTAT=0 подтверждение получено.

// Прочитать байт с Формированием подтверждения ACK/NACK
unsigned char I2C_readbyte(unsigned char set_confirm, unsigned char mode) {
   unsigned char I2CReadData;
   I2C_check(mode);       // проверка освобождения шины
   SSPIF = 0;                // обнуляем прерывание
   RCEN = 1;              // разрешить прием данных
   while(!SSPIF);        // ожидание завершения
   I2C_check(mode);       // проверка освобождения шины
   I2CReadData = SSPBUF;  // считать буфер
   I2C_check(mode);       // проверка освобождения шины
   // ACKDT - бит используется только в режиме Master Receive
   // 1 - нет подтверждение, 0 - подтверждение
   if (mode)  { ACKDT=0; }  else  { ACKDT=1; }
   SSPIF = 0;    
   ACKEN = 1;        // отправить подтверждение приема
   while(!SSPIF);    // проверка окончания передачи
   return(I2CReadData); }
//-------------------------------------------------------------------------------------

//Включение и настройка модуля I2C (MSSP)
void I2C_on(unsigned char mode, unsigned char speed) {
     // mode==1 - master, mode==0 - slave (7-bit адресация)
     // Устанавливаем порты - изначально они должны быть установлены на вход,
     // Когда выводы SCL и SDA настроены на вход, к ним подключен
     // Фильтр "glitch". В режиме 100кГц, когда они настроены на выход он
     // контроллирует длительность сигналов, независимо от тактовой частоты МК.
     SCL_PIN = 0;
     SCL_TRIS = 1;
     SDA_PIN = 0;
     SDA_TRIS = 1;
     // RBPU=1; - внутренние подтягивающие резисторы отключены
     
     // сбросить прерывания
     SSPBUF = 0;
       SSPIF = 0; // флаг прерывания от модуля MSSP (PIR1.3)
     SSPIE = 1; // 1/0 - разрешение/запрет прерываний от MSSP
     BCLIF = 0; // флаг прерывания при коллизии шины SSР когда он работает в режиме ведущий I2С (PIR2.3)
     BCLIE = 1; // 1/0 - разрешение/запрет прерывания при коллизии шины синхронного последовательного порта
     
     //Настраиваем регистры
     //SSPSTAT - регистр статуса модуля MSSP
     //Седьмой бит SMP - 1, управление длительностью фронта выключено, 100 кГц и 1МГц
     //Седьмой бит SMP - 0, управление длительностью фронта включено, 400 кГц
     if (speed) { SMP=1; } else { SMP=0; }
     //SSPCON1 и SSPCON2 - регистры управления модуля MSSP
     SSPCON2 = 0b00000000;
     if (mode) {
     SSPADD  = I2C_GEN_MASTER; // коэф генератора
     //SSPCON1.3-0 = 1000 — ведущий I2C;
     //SSPCON1.5 — включить модуль MSSP, бит SSPEN;
     SSPCON1 = 0b00101000; }
     else { SSPCON1 = 0b00100110; } }
 
void I2C_LCD_init (unsigned char address){
I2C_start();
I2C_sendbyte(address, 1);
I2C_stop();
}
 
void main(void)
{
TRISA=0x00;
TRISB=0x00;
TRISC=0x00;
//Все порты установлены как цифровой выход.
LATA=0x00;
LATB=0x00;
LATC=0x00;

PEIE = 1; // Периферийные прерывания разрешены
GIE = 1; // Глобальные прерывания разрешены
//GIE=0; - запрет всех прерываний
//IPEN = 0; - Disable priority levels on interrupts

doPEEK(1); // Привуээт!

I2C_on(1, 1); // Включаем I2C

// Адрес слейва в I2C занимает только 7 бит, начиная с 1го.
// А "нулевой" бит - признак цикла чтение/запись. Поэтому в адресе должно быть
// записано значение с нулем в "нулевом" бите - т.е. режим записи.

I2C_LCD_init(0x20<<1);

while(1) { doPEEK(1); }

}
Извините, если тут что-то банальное. Ранее я никогда не пользовался прерываниями, так что мог забыть что-то тривиальное... Хотя, вроде всё просмотрел уже. Ума не приложу где тут косяк.
CocuckuH вне форума   Ответить с цитированием
Старый 03.11.2015, 09:09   #2
besogon
Senior Member
 
Регистрация: 12.07.2012
Возраст: 30
Сообщений: 1,391
Вес репутации: 2927/61
besogon has a reputation beyond reputebesogon has a reputation beyond reputebesogon has a reputation beyond reputebesogon has a reputation beyond reputebesogon has a reputation beyond reputebesogon has a reputation beyond reputebesogon has a reputation beyond reputebesogon has a reputation beyond reputebesogon has a reputation beyond reputebesogon has a reputation beyond reputebesogon has a reputation beyond repute
По умолчанию Re: Не могу запустить аппаратный I2C на PIC18F258

CocuckuH
я не буду долго рассусоливать:
i2c в младших семействах microchip требует реализации особой машины состояний, которая весьма завязана на прерывания.

в общем случае нет никакого смысла ожидать что-либо в цикле - Вы непонятно зачем тратите машинное время, хотя могли занять машину чем-либо еще.

давайте допустим я Вам сброшу свой вариант исполнения драйвера для i2c и, допустим, драйвера для lm75a(простейший температурный датчик) - Вы посмотрите и сразу поймете что к чему.

естественно - это не повод слепо копировать и.т.д - везде есть варианты.
(тем более конкретно мой драйвер для устройств с внутренним адресом ограниченным одним байтом - нужно будет адресовать больше - переписать не сложно)

https://drive.google.com/folderview?...HM&usp=sharing

на форум не грузятся архивы - выложу через googledrive
besogon вне форума   Ответить с цитированием
Старый 03.11.2015, 09:12   #3
besogon
Senior Member
 
Регистрация: 12.07.2012
Возраст: 30
Сообщений: 1,391
Вес репутации: 2927/61
besogon has a reputation beyond reputebesogon has a reputation beyond reputebesogon has a reputation beyond reputebesogon has a reputation beyond reputebesogon has a reputation beyond reputebesogon has a reputation beyond reputebesogon has a reputation beyond reputebesogon has a reputation beyond reputebesogon has a reputation beyond reputebesogon has a reputation beyond reputebesogon has a reputation beyond repute
По умолчанию Re: Не могу запустить аппаратный I2C на PIC18F258

главный обработчик прерываний выглядит примерно так:
Код:
interrupt void interrupt_handler(void){
	if(INTCONbits.T0IF){
		core_timer_handler();
	}
	if(PIR3bits.SSP2IF){
		i2c2_routine_handler();
	}
	if(PIR3bits.BCL2IF){
		i2c2_collision_handler();
	}
}
besogon вне форума   Ответить с цитированием
Старый 03.11.2015, 13:43   #4
CocuckuH
Member
 
Регистрация: 27.05.2015
Возраст: 27
Сообщений: 32
Вес репутации: 100/10
CocuckuH will become famous soon enoughCocuckuH will become famous soon enough
По умолчанию Re: Не могу запустить аппаратный I2C на PIC18F258

То есть для прерываний обязательно должен быть обработчик?

Почему же в примерах в сети его нет нигде?
CocuckuH вне форума   Ответить с цитированием
Старый 03.11.2015, 13:58   #5
besogon
Senior Member
 
Регистрация: 12.07.2012
Возраст: 30
Сообщений: 1,391
Вес репутации: 2927/61
besogon has a reputation beyond reputebesogon has a reputation beyond reputebesogon has a reputation beyond reputebesogon has a reputation beyond reputebesogon has a reputation beyond reputebesogon has a reputation beyond reputebesogon has a reputation beyond reputebesogon has a reputation beyond reputebesogon has a reputation beyond reputebesogon has a reputation beyond reputebesogon has a reputation beyond repute
По умолчанию Re: Не могу запустить аппаратный I2C на PIC18F258

CocuckuH
итак.
прерывание в pic18 может быть реализовано 2 способами - это через 2 вектора(interrupt priority feature) или через 1 вектор(legacy).
2 вектора нужны если у Вас есть необходимость во время обработки прерывания с обычным приоритетом иметь возможность обработать прерывание с высоким приоритетом.
что такое вектор прерывания? - это адрес, куда попадает исполнение, как только произошло событие по которому требуется прервать последовательное исполнение программы и срочно что-то сделать.
0x0008 - обычный /высокий
0x0018 - низкий.
рассмотрим обычный режим.
код исполняется последовательно в обычном режиме.
случилось прерывание - исполнение попадает по адресу 0x0008, где у Вас расположен вызов некого обработчика прерываний.
в этом обработчике Вы смотрите, что было причиной прерывания и адекватно на него реагируете.
по завершению прерывания, исполнение возвращается к моменту, в котором Вы остановились.
в примере я не акцентировал внимание на сохранении контеста и.т.д.

все это написано в документации к чипу, который Вы собрались использовать в своем проекте.
besogon вне форума   Ответить с цитированием
Старый 03.11.2015, 14:01   #6
besogon
Senior Member
 
Регистрация: 12.07.2012
Возраст: 30
Сообщений: 1,391
Вес репутации: 2927/61
besogon has a reputation beyond reputebesogon has a reputation beyond reputebesogon has a reputation beyond reputebesogon has a reputation beyond reputebesogon has a reputation beyond reputebesogon has a reputation beyond reputebesogon has a reputation beyond reputebesogon has a reputation beyond reputebesogon has a reputation beyond reputebesogon has a reputation beyond reputebesogon has a reputation beyond repute
По умолчанию Re: Не могу запустить аппаратный I2C на PIC18F258

к слову, обработчики прерывания для pic18 еще недавно в какой-то теме очень подробно сусолились.
http://www.microchip.su/showthread.php?t=17373
соответственно смотреть код не TS, а достопочтенных граждан, которые с успехом помогли человеку превозмочь.
besogon вне форума   Ответить с цитированием
Старый 04.11.2015, 00:23   #7
CocuckuH
Member
 
Регистрация: 27.05.2015
Возраст: 27
Сообщений: 32
Вес репутации: 100/10
CocuckuH will become famous soon enoughCocuckuH will become famous soon enough
По умолчанию Re: Не могу запустить аппаратный I2C на PIC18F258

Ну ок, основную идею я понял - переписать всё под прерывания.

Но гляньте, всё-таки, код, пожалуйста.

Я так понимаю флаг SSPIF должен и без прерывания подыматься. Или нет?

Я хочу понимать почему оно не работает!
CocuckuH вне форума   Ответить с цитированием
Старый 04.11.2015, 09:10   #8
besogon
Senior Member
 
Регистрация: 12.07.2012
Возраст: 30
Сообщений: 1,391
Вес репутации: 2927/61
besogon has a reputation beyond reputebesogon has a reputation beyond reputebesogon has a reputation beyond reputebesogon has a reputation beyond reputebesogon has a reputation beyond reputebesogon has a reputation beyond reputebesogon has a reputation beyond reputebesogon has a reputation beyond reputebesogon has a reputation beyond reputebesogon has a reputation beyond reputebesogon has a reputation beyond repute
По умолчанию Re: Не могу запустить аппаратный I2C на PIC18F258

CocuckuH
Вы получаете коллизию шины?
Почему Вы не используете workaround бага MSSP?
Before configuring the module for I2C operation:
Configure the SCL and SDA pins as outputs by clearing their corresponding TRIS bits.
Force SCL and SDA low by clearing the corresponding LAT bits.
While keeping the LAT bits clear, configure SCL and SDA as inputs by setting their TRIS bits.
он почти в каждом pic18f, даже если в erratа нет.
сделайте проще пример, в котором хотите разобраться.
besogon вне форума   Ответить с цитированием
Старый 04.11.2015, 09:25   #9
Greg
Super Moderator
 
Регистрация: 25.02.2007
Адрес: Moscow, ODBS
Сообщений: 6,578
Вес репутации: 5056/154
Greg has a reputation beyond reputeGreg has a reputation beyond reputeGreg has a reputation beyond reputeGreg has a reputation beyond reputeGreg has a reputation beyond reputeGreg has a reputation beyond reputeGreg has a reputation beyond reputeGreg has a reputation beyond reputeGreg has a reputation beyond reputeGreg has a reputation beyond reputeGreg has a reputation beyond repute
По умолчанию Re: Не могу запустить аппаратный I2C на PIC18F258

Цитата:
Сообщение от besogon Посмотреть сообщение
на форум не грузятся архивы - выложу через googledrive
"ты же читаешь..."
грузятся рары и зипы
Вложения
Тип файла: zip i2c_example.tar.zip (1.8 Кб, 9 просмотров)
Greg вне форума   Ответить с цитированием
Старый 04.11.2015, 09:27   #10
besogon
Senior Member
 
Регистрация: 12.07.2012
Возраст: 30
Сообщений: 1,391
Вес репутации: 2927/61
besogon has a reputation beyond reputebesogon has a reputation beyond reputebesogon has a reputation beyond reputebesogon has a reputation beyond reputebesogon has a reputation beyond reputebesogon has a reputation beyond reputebesogon has a reputation beyond reputebesogon has a reputation beyond reputebesogon has a reputation beyond reputebesogon has a reputation beyond reputebesogon has a reputation beyond repute
По умолчанию Re: Не могу запустить аппаратный I2C на PIC18F258

Greg
факт. мне тоже казалось что я когда-то с успехом выкладывал архивы на форум.
besogon вне форума   Ответить с цитированием
Старый 04.11.2015, 09:53   #11
Greg
Super Moderator
 
Регистрация: 25.02.2007
Адрес: Moscow, ODBS
Сообщений: 6,578
Вес репутации: 5056/154
Greg has a reputation beyond reputeGreg has a reputation beyond reputeGreg has a reputation beyond reputeGreg has a reputation beyond reputeGreg has a reputation beyond reputeGreg has a reputation beyond reputeGreg has a reputation beyond reputeGreg has a reputation beyond reputeGreg has a reputation beyond reputeGreg has a reputation beyond reputeGreg has a reputation beyond repute
По умолчанию Re: Не могу запустить аппаратный I2C на PIC18F258

Цитата:
Сообщение от CocuckuH Посмотреть сообщение
Ну ок, основную идею я понял - переписать всё под прерывания.
Я хочу понимать почему оно не работает!
не надо переписывать - прерывание сейчас для вас это слишком сложно.
у вас модуль просто не работает. потому что тоже сложный (в этих пиках ещё и очень кривой).
напишите и заставьте работать программный и2с, там работы на пол-дня. Если повезет, может заодно поймете почему не работал аппаратный.

это не стеб, а реальный совет.
Greg вне форума   Ответить с цитированием
Старый 04.11.2015, 18:06   #12
CocuckuH
Member
 
Регистрация: 27.05.2015
Возраст: 27
Сообщений: 32
Вес репутации: 100/10
CocuckuH will become famous soon enoughCocuckuH will become famous soon enough
По умолчанию Re: Не могу запустить аппаратный I2C на PIC18F258

Цитата:
Before configuring the module for I2C operation:
Configure the SCL and SDA pins as outputs by clearing their corresponding TRIS bits.
Force SCL and SDA low by clearing the corresponding LAT bits.
While keeping the LAT bits clear, configure SCL and SDA as inputs by setting their TRIS bits.
Так, погодите-ка, так это что, надо было последовательно сделать, сначала выходы, очистить защёлку, а потом при неизменной защёлке как входы?
CocuckuH вне форума   Ответить с цитированием
Старый 05.11.2015, 17:26   #13
CocuckuH
Member
 
Регистрация: 27.05.2015
Возраст: 27
Сообщений: 32
Вес репутации: 100/10
CocuckuH will become famous soon enoughCocuckuH will become famous soon enough
По умолчанию Re: Не могу запустить аппаратный I2C на PIC18F258

В общем я разобрался в чём дело.

А дело было в банальном, как обычно.

В общем, в нескольких руководствах речь шла о pulldown-резисторах. И в каком-то русскоязычном факе по хардварному i2c я тоже встречал упоминания, что нужно шунтировать линии i2c на землю. Что я, собственно, и сделал.

Сейчас, когда сел перечитывать спецы i2c, обратил внимание на тот факт, что во всех специях идёт речь о pullup, т.е. о резисторах подтягивающих к питанию.

И действительно, глянул в сети - везде на схемах к питанию они ведут.

Короче, я переделал и i2с у меня заработал. Я даже подобрал адрес дисплея. Осталось только разобраться с алгоритмом работы с дисплеем через i2c. Я думаю я справлюсь. Всем спасибо.
CocuckuH вне форума   Ответить с цитированием
Ответ


Здесь присутствуют: 1 (пользователей: 0 , гостей: 1)
 
Опции темы
Опции просмотра

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.

Быстрый переход

Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
что за зверь - Скатерограмма Edua Общетехнические вопросы 17 01.03.2013 23:33
PIC16F84a stepka Вопросы начинающих 56 24.03.2010 18:30


Часовой пояс GMT +3, время: 18:47.


Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, Jelsoft Enterprises Ltd. Перевод: zCarot