SerYoga72 Опубликовано 19 апреля, 2019 Поделиться Опубликовано 19 апреля, 2019 Приветствую всех. Подскажите не совсем программисту (или совсем не программисту) как грамотно реализовать программный SPI. МК CC430F5137 + OLED дисплей WEH000802A от Winstar. Данные 10 бит. Аппаратный в контроллере позволяет только 8, выход свой написать. Написал, но мне это не нравиться, знаю что можно намного проще, но не нахожу решения. Да и как то странно с портами в этом контроллере работается, нельзя (или не знаю как) данные напрямую в порт кидать, типа P1.0 = 1; А только BITами оперировать??? Вот что у меня получилось, смеяться разрешается )) // Обработчик дисплея // // Маразм для програмного SPI void SCL(uchar b) { if (b==1) (P1OUT |= BIT7); else P1OUT &= ~BIT7; } //Строб void CSB(uchar b) { if (b==1) (P1OUT |= BIT4); else P1OUT &= ~BIT4; } //Выбор чипа void SDI(uchar b) { if (b==1) (P1OUT |= BIT6); else P1OUT &= ~BIT6; } //Передаваемые данные void SDO(uchar b) { if (b==1) (P1OUT |= BIT5); else P1OUT &= ~BIT5; } //Принимаемые данные // Вывод управляющей команды для дисплея void WriteCMD(uchar CMD) { uchar i; CSB(0); SDI(0); _delay_cycles(100); SCL(0); _delay_cycles(100); SCL(1); SDI(0); _delay_cycles(100); SCL(0); _delay_cycles(100); SCL(1); _delay_cycles(100); for(i=0;i<8;i++) { uchar t = ((CMD>>(7-i)) & 0x01); // Как уйти от переменной t ????? SDI(t); SCL(0); _delay_cycles(100); SCL(1); _delay_cycles(100); } CSB(1); } /*============================================ Вывод одиночного символа на дисплей ============================================*/ void WriteOneDAT(uchar DAT) { uchar i;; CSB(0); SDI(1); _delay_cycles(100); SCL(0); _delay_cycles(100); SCL(1); SDI(0); _delay_cycles(100); SCL(0); _delay_cycles(100); SCL(1); _delay_cycles(100); for(i=0;i<8;i++) { uchar t =((DAT>>(7-i)) & 0x01); SDI(t); SCL(0); _delay_cycles(100); SCL(1); _delay_cycles(100); } CSB(1); } Технически разница между Командой и Данными в первом бите SDI и объединить эти две функции наверно не проблема, но я уверен что это можно написать как то грамотнее ... Как в этом контроллере с портами работать кроме как P1OUT |= BIT1 ??? Нельзя как то типа P1OUT_1 = 1; ?? Где то в буржуйской литературе мапинг какой то проскакивал, но там я вообще не вьехал про что это, для чего это.... Заранее Всем Благодарен. 0 Ссылка на комментарий Поделиться на другие сайты Поделиться
ARV Опубликовано 19 апреля, 2019 Поделиться Опубликовано 19 апреля, 2019 Вообще говоря, программный SPI настолько элементарен, что просто не заслуживает какого-либо обсуждения. // маска последнего выводимого бита #define LAST_BIT (1<<10) // макрос SDI() переделать так, чтобы он возвращал bool-уровень на пине uint16_t spi_io(uint16_t data){ uint16_t result = 0; for(uint16_t mask = 1; mask <= LAST_BIT; mask <<= 1){ SDO(data & mask); SCL(1); result |= SDI() ? mask : 0; SCL(0); } return result; } Вам лишь надо уточнить, в том ли направлении в моём коде идет сдвиг и в нужном ли режиме устанавливается SCK. 0 Если забанить всех, кто набрался смелости думать независимо, здорово будет на форуме - как на кладбище: тишина, птички поют... Ссылка на комментарий Поделиться на другие сайты Поделиться
20% скидка на весь каталог электронных компонентов в ТМ Электроникс!Акция "Лето ближе - цены ниже", успей сделать выгодные покупки!Плюс весь апрель действует скидка 10% по промокоду APREL24 + 15% кэшбэк и бесплатная доставка!Перейти на страницу акции Реклама: ООО ТМ ЭЛЕКТРОНИКС, ИНН: 7806548420, info@tmelectronics.ru, +7(812)4094849
SerYoga72 Опубликовано 19 апреля, 2019 Автор Поделиться Опубликовано 19 апреля, 2019 Я понимаю, но как я сказал - я совсем не программист, когда то давно писал на ассемблере. Вот например Ваш код мне сложен для понимания, я его конечно раскурю, я Вам благодарен, но придумать я бы такое не смог. Еще раз благодарю. Еще бы кто по работе с портами просветил... 0 Ссылка на комментарий Поделиться на другие сайты Поделиться
Выбираем схему BMS для корректной работы литий-железофосфатных (LiFePO4) аккумуляторов Обязательным условием долгой и стабильной работы Li-FePO4-аккумуляторов, в том числе и производства EVE Energy, является применение специализированных BMS-микросхем. Литий-железофосфатные АКБ отличаются такими характеристиками, как высокая многократность циклов заряда-разряда, безопасность, возможность быстрой зарядки, устойчивость к буферному режиму работы и приемлемая стоимость. Но для этих АКБ, также как и для других, очень важен контроль процесса заряда и разряда, а специализированных микросхем для этого вида аккумуляторов не так много. Инженеры КОМПЭЛ подготовили список имеющихся микросхем и возможных решений от разных производителей. Подробнее>> Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161
ARV Опубликовано 19 апреля, 2019 Поделиться Опубликовано 19 апреля, 2019 Только что, SerYoga72 сказал: Еще бы кто по работе с портами просветил... А что с ними не так? 0 Если забанить всех, кто набрался смелости думать независимо, здорово будет на форуме - как на кладбище: тишина, птички поют... Ссылка на комментарий Поделиться на другие сайты Поделиться
SerYoga72 Опубликовано 19 апреля, 2019 Автор Поделиться Опубликовано 19 апреля, 2019 Пример Порт 1 Пин 0 P1OUT |= BIT0 ; // P1.0 установили в единицу P1OUT &= ~BIT0; // Установили в ноль Это хорошо для моргания одним светодиодом, но часто проще сразу записать 1 или 0 в нужный порт, типа P1.0 = 1; // Неужели подобное невозможно реализовать в MSP430 ?? Я как только не пробовал... И нигде не нахожу. Для реализации SPI пришлось создать четыре функции, я считаю это бредом каким то, если честно. // Маразм для програмного SPI void SCL(uchar b) { if (b==1) (P1OUT |= BIT7); else P1OUT &= ~BIT7; } //Строб void CSB(uchar b) { if (b==1) (P1OUT |= BIT4); else P1OUT &= ~BIT4; } //Выбор чипа void SDI(uchar b) { if (b==1) (P1OUT |= BIT6); else P1OUT &= ~BIT6; } //Передаваемые данные void SDO(uchar b) { if (b==1) (P1OUT |= BIT5); else P1OUT &= ~BIT5; } //Принимаемые данные И кстати, в Вашей версии реализации вот этот кусок почему то не работает: SDO(data & mask); Еще сильно не думал, но даже если data имеет значения 0xFFFF, SDO все равно имеет значение 0, всегда ноль.... Даже примерно не могу понять почему... Я использую CCS. И кстати булевых переменных тут что то же нет? Обявления типа bool var; выдает ошибку неопределенный тип.... 0 Ссылка на комментарий Поделиться на другие сайты Поделиться
ARV Опубликовано 19 апреля, 2019 Поделиться Опубликовано 19 апреля, 2019 (изменено) 41 минуту назад, SerYoga72 сказал: И кстати, в Вашей версии реализации вот этот кусок почему то не работает потому что данные data и mask 16-битные, а функцию вы определили с 8-битным параметром. и вообще, я рассчитывал, что SDO будет макросом, которому в общем-то плевать на разрядность... 41 минуту назад, SerYoga72 сказал: P1.0 = 1; // Неужели подобное невозможно реализовать в MSP430 ?? Такое вообще нельзя реализовать на языке Си - это вы насмотрелись "кода" на недосишном языке CVAVR. Если сильно-сильно хочется именно подобной записи, то придется попариться со структурами и указателями... Но я вам не буду этого советовать - у вас и так проблем хватает. 41 минуту назад, SerYoga72 сказал: P1OUT |= BIT0 ; // P1.0 установили в единицу P1OUT &= ~BIT0; // Установили в ноль А вот это самая что ни на есть кошерная запись для Си. Именно так и правильно манипулировать битами. #define SDO(x) do{ if(x) P1OUT |= BIT5; else P1OUT &= ~BIT5; } while(0) #define SDI() (P1IN & BIT7) #define SCK(x) do{ if(x) P1OUT |= BIT6; else P1OUT &= ~BIT6; } while(0) Как-то так всего-навсего... Я не знаком с вашей платформой, но для SDI по-моему нельзя использовать порт вывода P1OUT... я написал P1IN, хотя не уверен, что это правильно... Изменено 19 апреля, 2019 пользователем ARV 0 Если забанить всех, кто набрался смелости думать независимо, здорово будет на форуме - как на кладбище: тишина, птички поют... Ссылка на комментарий Поделиться на другие сайты Поделиться
SerYoga72 Опубликовано 20 апреля, 2019 Автор Поделиться Опубликовано 20 апреля, 2019 Заставил я это работать )). Благодарю. Теперь вопрос для повышения общего уровня образованности так сказать, ну если Вы не против.: Вы предлагаете такую реализацию: 18 часов назад, ARV сказал: #define SDO(x) do{ if(x) P1OUT |= BIT5; else P1OUT &= ~BIT5; } while(0) #define SDI() (P1IN & BIT7) #define SCK(x) do{ if(x) P1OUT |= BIT6; else P1OUT &= ~BIT6; } while(0) У меня реализовано так: void SCL(uchar b) { if (b) (P1OUT |= BIT7); else P1OUT &= ~BIT7; } //Строб void CSB(uchar b) { if (b) (P1OUT |= BIT4); else P1OUT &= ~BIT4; } //Выбор чипа void SDO(uint b) { if (b) (P1OUT |= BIT6); else P1OUT &= ~BIT6; } //Передаваемые данные Чем Ваша реализация лучше? (Вопрос не для спора а для понимания) И для чего цикл do-while ? По поводу SDI (принимаемых данных) Вы правы, просто я данные пока не собирался принимать и написал на автопилоте P1OUT. Заранее благодарен. P.S. Как уменьшить межстрочный интервал в форуме? 0 Ссылка на комментарий Поделиться на другие сайты Поделиться
SerYoga72 Опубликовано 20 апреля, 2019 Автор Поделиться Опубликовано 20 апреля, 2019 Я кажется понял, если я использую #define то при компиляции данный код вставляется в место вызова и перехода не происходит, а в моем случае происходит переход в функцию и возврат из нее, то есть так мы экономим процессорные тики, я правильно понял? А для чего do-while ? 0 Ссылка на комментарий Поделиться на другие сайты Поделиться
ARV Опубликовано 20 апреля, 2019 Поделиться Опубликовано 20 апреля, 2019 Да, макросы повышают быстродействие, ведь требования к SPI обычно "чем быстрее, тем лучше". А do-while - это кошерная перестраховка на всякий случай. Во многих случаях можно и без этого, и данный случай как раз такой, просто делаю по привычке. Обычно do-while актуально для макросов, состоящих из нескольких операторов, и в данном случае не дает никаких преимуществ, т.к. оператор один. 0 Если забанить всех, кто набрался смелости думать независимо, здорово будет на форуме - как на кладбище: тишина, птички поют... Ссылка на комментарий Поделиться на другие сайты Поделиться
SerYoga72 Опубликовано 20 апреля, 2019 Автор Поделиться Опубликовано 20 апреля, 2019 Премного Вам благодарен! 0 Ссылка на комментарий Поделиться на другие сайты Поделиться
Рекомендуемые сообщения
Присоединяйтесь к обсуждению
Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.
Примечание: Ваш пост будет проверен модератором, прежде чем станет видимым.