SerYoga72

MSP430. Грамотная реализация програмного SPI

10 posts in this topic

SerYoga72    0

Приветствую всех.

Подскажите не совсем программисту (или совсем не программисту) как грамотно реализовать программный 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;  ?? Где то в буржуйской литературе мапинг какой то проскакивал, но там я вообще не вьехал про что это, для чего это....

Заранее Всем Благодарен.

 

 

 

 

 

Share this post


Link to post
Share on other sites
ARV    761

Вообще говоря, программный 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.

Share this post


Link to post
Share on other sites
SerYoga72    0

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

Еще раз благодарю.

Еще бы кто по работе с портами просветил...

Share this post


Link to post
Share on other sites

Приглашаем на вебинар «Создание беспроводных устройств на системах-на-кристалле семейства SimpleLink компании TI»

Компания Компэл, совместно с Texas Instruments приглашают 26 июня принять участие в вебинаре, где инженер по применению беспроводных технологий компании TI расскажет, как на новых беспроводных системах можно реализовать несколько полезнейших в повседневной жизни функций для ваших устройств. С развитием элементной базы TI становится возможной реализация более удобных, функциональных и безопасных систем, недоступных ранее. Вебинар проводит инженер по применению беспроводных технологий в TI Мари Хернес(будет дублированный перевод).

Подробнее...

ARV    761
Только что, SerYoga72 сказал:

Еще бы кто по работе с портами просветил...

А что с ними не так?

Share this post


Link to post
Share on other sites
SerYoga72    0

Пример Порт 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;  выдает ошибку неопределенный тип.... 

Share this post


Link to post
Share on other sites

Видео вебинара «Уникальный подход MORNSUN к разработке DC/DC-преобразователей. Что на выходе?»

На сайте КОМПЭЛ доступны материалы вебинара, посвященные последнему поколению DC/DC преобразователей с фиксированным входом R3 от MORNSUN. Вы можете посмотреть видеозапись, ознакомиться с презентацией и ответами на вопросы.

Подробнее...

ARV    761
Posted (edited)
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, хотя не уверен, что это правильно...

Edited by ARV

Share this post


Link to post
Share on other sites
SerYoga72    0

Заставил я это работать )). Благодарю.  Теперь вопрос для повышения общего уровня образованности так сказать, ну если Вы не против.:

Вы предлагаете такую реализацию:

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. Как уменьшить межстрочный интервал в форуме?

Share this post


Link to post
Share on other sites
SerYoga72    0

Я кажется понял, если я использую #define то при компиляции данный код вставляется в место вызова и перехода не происходит, а в моем случае происходит переход в функцию и возврат из нее, то есть так мы экономим процессорные тики, я правильно понял?

А для чего do-while ?

Share this post


Link to post
Share on other sites
ARV    761

Да, макросы повышают быстродействие, ведь требования к SPI обычно "чем быстрее, тем лучше". А do-while - это кошерная перестраховка на всякий случай. Во многих случаях можно и без этого, и данный случай как раз такой, просто делаю по привычке. Обычно do-while актуально для  макросов, состоящих из нескольких операторов, и в данном случае не дает никаких преимуществ, т.к. оператор один.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now


  • Similar Content

    • By mine1
      Наткнулся на библиотеку hal_xxx.c от TI для MSP430.
      Ни как не могу найти, где взять взять полное семейство этих библиотек. Поделитесь ссылочной  
      hal_UCS.c
    • By Isaev_ivan
      Доброго времени суток всем!
      Недавно возникла потребность передачи данных из микроконтроллера в ПК. Написал код на ассемблере, опираясь на Code_examples от TI, и то, что получилось, приведено ниже:
      #include "msp430F1232.h"
      RSEG CSTACK
      DS16 0
      RSEG CODE
      ;---------------------------------------------------------------------
      ; Установка тактирования от кварца
      ;---------------------------------------------------------------------
      RESET mov #SFE(CSTACK),SP
      mov #WDTPW+WDTHOLD,&WDTCTL ;OSTANOVKA WDT
      BIC #OSCOFF, SR ; tAKTIROVANIE OT KVARCA
      BIS.B #XTS, BCSCTL1
      L1 BIC.B #OFIFG, &IFG1
      MOV #0FFh, R15
      L2 DEC R15
      JNZ L2
      BIT.B #OFIFG, &IFG1
      JNZ L1
      BIS.B #SELM_3, &BCSCTL2
      ;--------------------------------------------------------------------
      ; Инициализация USART
      ;--------------------------------------------------------------------
      mov.b #200,R7
      bis.b #SWRST,&UCTL0;
      bis.b #030h,&P3SEL; P3.4,5 - USART
      bis.b #UTXE0+URXE0,&ME2; Включение передачи и приема
      bis.b #CHAR, &UCTL0; Формат данных 8-разрядный
      mov.b #SSEL0, &UTCTL0; UCLK=ACLK
      mov.b #0100b,&UBR00; 5MHz/19200 = 260.4 = 100000100b
      mov.b #0001b,&UBR10;
      mov.b #0000, &UMCTL0; Без модуляции
      bic.b #SWRST,&UCTL0; Сброс USART не включен
      bis.b #URXIE0+UTXIE0,&IE2
      bis.b #UTXIFG0,&IFG2; Флаг гтовности к прерыванию
      Loop bis.w #LPM3+GIE,SR
      nop
      jmp Loop
      ;-------------------------------------------------------------------
      USART0TX_ISR;
      ;-------------------------------------------------------------------
      mov.b R7, &TXBUF0;
      reti
      ;--------------------------------------------------------------------
      ; Векторы прерываний
      ;--------------------------------------------------------------------
      COMMON INTVEC
      ORG RESET_VECTOR
      DW RESET
      ORG USART0TX_VECTOR
      DW USART0TX_ISR
      END.
      Из программы видно, что я просто хочу передать содержимое R7 в ПК. Трудность заключается в том, что это значение передается не всегда. Запускаю программу, которая считывает информацию с com порта (программа работает 100% правильно), она в тестовый файл записывает значение 200(правильное значение). В следующий раз, после перезапуска программы, в текстовый файл она записывает величину 14. Потом снова 200. И я не пойму, что с ней происходит! Кто знает, отзовитесь пожалуйста
    • By yang
      I am Chinese student, now studying in St. Petersburg. I'm here one year, so i am not very good in Russian,written in English. I would like to know some new friends like programming and design, I want to participate in some professional game in Russia or complete some projects with my friends. If you need, I can help you buy some cheap things in China.If you have spare time or want to learn Chinese, hope you can help me learn the Russian language.This is part of my profile.




    • Guest Duck
      By Guest Duck
      Стоит изучать MSP430?
      Как я понимаю cortex-m он превосходит только энергоэффективностью? Или уже нет?
    • By tim-ua
      Я совсем новичок в МК, столкнулся с проблемой при подключении msp430 к bluetooth модулю. Модуль раньше работал на ардуине но с этой платой ни как не заводится.
      Подключить модуль к планшету получается (в терминале на планшете приходят обратно вводимые символы если замкнуть на модуле RX и TX). Но как дальше его подключить к msp430 я не понял. Пробовал так: P1.1 -> TX, p1.2 -> RX , пробовал менять комбинацию перемычек SW uart \ HW uart.
      Прошивка:

      void setup() { Serial.begin(9600); } void loop() { Serial.println("Test"); delay(100); }
      Возможно ли их вообще подключить?

  • Сообщения

    • Все,что надо- согласовать высокоомный выход ЗС с низким входным УНЧ.Усиление по напряжению. более чем....  Вот такое и прокатит, Более конкретно , надо слушать.....
    • лично меня никогда не интересовали методы нахождения ошибок по возвращаемому результату и восстановления информации. думаю, и тебе такие тонкости не нужны. более того, я в своих поделках ограничиваюсь чтением первых двух байтов с температурой. а если бояться, что чтение из датчика идет с ошибками,  тогда надо и бояться, что команды до датчика доходят с ошибками. а там не далеко и до паранойи...
    • Очего сразу глобальной? Любой. Глобальные переменные - это палка об двух концах, увлекаться ими без конкретной нужды не стоит. Конечно есть. Просто следуйте простому правилу: если что-то делается несколько раз с разными данными, это должно быть функцией. У вас есть функция вывода символа на дисплей. Чем отличается вывод строки символов от вывода одного символа? Тем, что повторяется несколько раз. Чем отличается вывод строки "Вася" от строки "123"? Ничем. Следовательно, вывод строки должен быть функцией. Как вывести число? Можно так, как вы, а можно иначе: превратить число в его строковое (т.е. сивольное) представление и вывести эту строку. А для превращения числа в строку применить библиотечную функцию itoa - её именно для того и придумали, чего ж добру пропадать?  И ваш код из предыдущего поста превратится в что-то такое: /* забудем это, как страшный сон lcd_dat('R'); lcd_dat('C'); lcd_dat('_'); lcd_dat('2'); lcd_dat('='); lcd_dat(((crc_2/100)%10)+48); lcd_dat(((crc_2/10)%10)+48); lcd_dat((crc_2%10)+48); */ // сделаем функцию вывода строки на ЖКИ void lcd_put_str(char *s){ while(*s) lcd_dat(*s++); } // сделаем функцию вывода числа void lcd_put_int(int i){ char tmp[10]; itoa(i, tmp, 10); lcd_put_str(tmp); } lcd_put_str("RC_2="); // выведем информационный текст lcd_put_int(crc_2); // и выведем переменную   Зачем?! Просто return crc; и тогда можно даже так lcd_put_int(checkcrc());   Совершенно бесполезная трата времени для прикладных целей! Если вы не решили посвятить себя теории программирования, то вам эти знания не будут полезны от слова совсем. Тем более что CRC8 не позволяет однозначно выделить искаженный бит, даже если он один, а если несколько - и подавно.
    • Василичь! Твоё фирменное хамство я пропускаю и не комментирую. А, по поводу - Где ты увидел 2,2 ком там резистор - так, на твоей бумажке! Откуда я знаю, что творится в твоей голове, что и где ты пишешь, и что означают твои цифры? На схеме этот конденсатор нигде и никак не обозначен. Вот я и прочитал 750 Ом - 0.03%, 2200 Ом - 0.114% А, человек, придумавший термин искажения типа "клюшка" и измеряющий IMD с помощью одной единственной частоты, по моему мнению, способен нести абсолютно любую пургу. Я же написал Вот я и прочёл, что угодно. Хочешь выложить информацию - приведи её в Божеский вид, однозначно понятный людям. А выкладывая только тебе понятные черновики, не удивляйся, что люди чего то не поймут.    
    • VD2 и VD3 не нужны. С6 большой номинал, хватило бы и 220-180n И вообще, лучше делать с обмоткой самопитания или от средней точки ключей через конденсатор.  как в этой схеме