Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Как сделать нормальный putchar
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > MSP430
tvilsa
Всем привет.
В CodeVision для AVR использовал конструкцию
putchar('S') и на экране в терминале получал символ S.
В ИАРе такая конструкция не работает. Почему?
Обмен MSP PC нормальный. Передаю значения путем помещения его в TXBUF0.
Как сделать чтоб работала конструкция putchar('s')?
Заранее спасибо.
Dog Pawlowa
Цитата(tvilsa @ Mar 16 2009, 11:44) *
Обмен MSP PC нормальный. Передаю значения путем помещения его в TXBUF0.
Как сделать чтоб работала конструкция putchar('s')?

А UART проинициализирован? Скорость, разрешение передачи...
tvilsa
Цитата(Dog Pawlowa @ Mar 16 2009, 11:51) *
А UART проинициализирован? Скорость, разрешение передачи...


А при чем здесь это?
Я же написал что обмен уже работает, но только через непосредственную запись значений в регистр.
Как сделать чтоб работал putchar?
MrYuran
Насколько я помню, в ИАре putchar() и printf() - это обёртки функции put_one_symbol(), которую надо определить самостоятельно (по крайней мере я так делал)

Точно утверждать не могу, т.к. сейчас под рукой сабжа нет, и пользовался этими функциями давненько
VSt&
По крайней мере, для IAR EWARM требовалась функция size_t __write(int handle, const unsigned char *buffer, size_t size); - самописная, выкладывающая посимвольно строку в UART; а также, в опциях проекта "Linker" убрать галочки "With I/O emulation modules", "Buffered Terminal Output". Привожу исключительно по аналогии, т.к. IAR для MSP не пользовал.
Dog Pawlowa
Цитата(tvilsa @ Mar 16 2009, 11:22) *
А при чем здесь это?
Я же написал что обмен уже работает, но только через непосредственную запись значений в регистр.
Как сделать чтоб работал putchar?

То есть? где то записанная запись значения в регистр работает, а в самом putchar - нет?


Цитата(MrYuran @ Mar 16 2009, 11:34) *
Насколько я помню, в ИАре putchar() и printf() - это обёртки функции put_one_symbol(), которую надо определить самостоятельно (по крайней мере я так делал)

Странно, может в старых версиях так было.
Сам putchar нужно определить самостоятельно. А printf - обертка, конечно же.
tvilsa
Цитата(Dog Pawlowa @ Mar 16 2009, 12:53) *
То есть? где то записанная запись значения в регистр работает, а в самом putchar - нет?


именно. передача простой записью в регистр работает т.е. при выполнении
TXBUF0 = 0х30;
работает,а
putchar('s'); не работает
Dog Pawlowa
Цитата(tvilsa @ Mar 16 2009, 13:07) *
именно. передача простой записью в регистр работает т.е. при выполнении
TXBUF0 = 0х30;
работает,а
putchar('s'); не работает

Дык в самом putchar что записано?! Приведите текст этой функции.
rezident
Я с вас дивлюся, мужики! Неужели пару страничек хелпа сложно прочитать? laughing.gif
tvilsa
Цитата(rezident @ Mar 16 2009, 20:35) *
Я с вас дивлюся, мужики! Неужели пару страничек хелпа сложно прочитать? laughing.gif


Если я правильно понял то функцию putchar надо описывать самому.
Простое использование putchar('s') непрокатит.
Жаль. И зачем она тогда нужна?
VAI
Библиотечная пустая функция putchar() нужна как затычка. Пустая функция __low_level_init() у Вас вопросы не вызывает?
При отсутствии Вашей функции putchar() вызывается она.
Ведь вывод можно делать и на индикатор (графический, семисигментный, символьный и т.д.), и последовательный порт, и даже в какую нибудь eeprom-ку.
Кроме Вас никто не знает, куда будет выводить Ваш putchar() и к каким ногам/портам он подключен.
Так вот Ваша функция putchar() должна обеспечивать низкоуровневый вывод символа на Ваше устройство.

Код
/* --- putchar() ------------------------------------------------------------ **
*  Вывод байта в терминал
* -------------------------------------------------------------------------- */
int putchar( int c )
{
  if ( !c )
    return( 0 );
  return( uart0_tx( c ));
}

// или что-то такое, немного кастрировано

/* --- putchar() ------------------------------------------------------------ **
*  Вывод байта на символьный индикатор или принтер
* Универсальный, для ЖКИ любого размера.
* Используется перекодировка из таблицы win1251 в таблицу, применяемую в ЖКИ.
*  \a    (\007) - Звуковой сигнал 50 ms, окончания звука не ожидает, пищит в фоне.
*  \b    (\010) - Возврат на шаг (забой), из начала первой строки перейдет в конец последней
*  \t    (\011) - Табуляция горизонтальная (сдвиг по ...). С конца последней строки переходит на начало первой!
*  \n    (\012) - Перевод строки (новая строка), с последней строки индикатора осуществляется переход на первую.
*  \v    (\013) - Переход в начало экрана (gotoxy(0,0))
*  \f    (\014) - Очистка экрана + Переход в начало экрана (gotoxy( 0, 0 ))
*  \r    (\015) - Возврат каретки (на начало строки)
*  \0    (\000) - Ничего не делает, просто возвращает 0, и все.
*  \016         - символ '\000' дополнительного знакогенератора
*  \017         - символ '\007' дополнительного знакогенератора
*  \033         - ESC-команда см. esc_cmd.h
* lcd_pos указывает на позицию курсора, т.е. после выполнения функции указывает на место, в которое будет
* выводиться при следующем вызове функции. Позиции STROKA * STOLB и 0 эквивалентны!
* -------------------------------------------------------------------------- */
int putchar( int c )
{
static const char perecod[] =  // перекодировка русских букв из таблицы win1251 в таблицу, применяемую в ЖКИ
{ 'A' , 0xa0, 'B' , 0xa1, 0xe0, 'E' , 0xa3, 0xa4, 0xa5, 0xa6, 'K' , 0xa7, 'M' , 'H' , 'O' , 0xa8,  // 0xc0..0xcf
  'P' , 'C' , 'T' , 0xa9, 0xaa, 'X' , 0xe1, 0xab, 0xac, 0xe2, 0xad, 0xae, 'b' , 0xaf, 0xb0, 0xb1,  // 0xd0..0xdf
  'a' , 0xb2, 0xb3, 0xb4, 0xe3, 'e' , 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 'o' , 0xbe,  // 0xe0..0xef
  'p' , 'c' , 0xbf, 'y' , 0xe4, 'x' , 0xe5, 0xc0, 0xc1, 0xe6, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7   // 0xf0..0xff
};
static int previos;                     // 10.05.04г. добавил для корректной работы последовательностей "\f\n", "\v\n" и "\n\n"
int c_old = 0;

//   if ( c )
//   { if ( c >= 'А' )                     // А - по русски это 0xc0 в win1251
//       c = perecod[c - 'А'];             // русские буквы в кодировке win1251
//     else if ( c >= 0x80 )               // спецсимволы, расположенные в знакогенераторе lcd
//       c += 0x40;                        // мы их немного перенесли (символы с кодом 0xc0..0xff перенесены в область 0x80..0xc0

int a;                                  // пришлось ввести переменную и вынести ее расчет из perecod[c - 'А'], ато "крутой" оптимизатор от ИАР МСП v3.30а заоптимизировывает...

  if ( c )
  { if ( flag.redirect == ON )                                    // перенаправление putchar() на принтер
      return( prn_byte( c ));
    c_old = c;
    a = c - 'А';                                                  // А - по русски это 0xc0 в win1251
    if ( a >= 0 )
      c = perecod[a];                                             // А - по русски это 0xc0 в win1251
    else if ( c >= 0x80 )                                         // спецсимволы, расположенные в знакогенераторе lcd
    { if ( c == 0xa8 )                                            // буква "Ё"
        c = 0xa2;
      else if ( c == 0xb8 )                                       // буква "ё"
        c = 0xb5;
      else
        c += 0x40;                                                // мы их немного перенесли (символы с кодом 0xc0..0xff перенесены в область 0x80..0xc0
    }
    switch ( c )
    { case '\a':                                                  // Звуковой сигнал
        beep( 50 );
        break;
      case '\b':                                                  // возврат на один символ (забой)
        if ( !lcd_pos )
          lcd_pos = STROKA * STOLB;
        if (( lcd_pos-- % STROKA ) == 0 )                         // последний символ в конце строки
          goto_pos();
        else
          lcd_send_com( LCD_CURS_MOV_LEFT );
        lcd_send_dat( ' ' );
        lcd_send_com( LCD_CURS_MOV_LEFT );
        break;
      case '\t':                                                  // табуляция. С конца последней строки переходит на начало первой!
        if (( lcd_pos += TAB_SIZE ) <= STROKA * STOLB )
          lcd_pos = ( lcd_pos / TAB_SIZE ) * TAB_SIZE;
        else
          lcd_pos = 0;
        goto_pos();
        break;
      case '\n':                                                  // на новую строку
        if ( previos == '\n' || previos == '\f' || previos == '\v' || ( lcd_pos % STROKA ) != 0 )    // игнорируем, если позиция кратна строке (уже сделан \n)
        { lcd_pos /= STROKA;
          if ( ++lcd_pos == STOLB )
            lcd_pos = 0;
          else
            lcd_pos *= STROKA;
          goto_pos();
        }
        break;
      case '\v':                                                  // в начало экрана (gotoxy(0,0))
        if ( flag.cls_ind != ON )                                 // если установлен флаг - надо делать '\f'
        { lcd_send_com( LCD_HOME );                               // lcd_gotoxy( 0, 0 );
          lcd_pos = 0;
          break;
        }
      case '\f':                                                  // очистка экрана + gotoxy(0,0)
        lcd_send_com( LCD_CLS_HOME );
        flag.cls_ind = OFF;
        lcd_pos = 0;
        break;
      case '\r':                                                  // возврат на начало строки без очистки экрана
        if ( lcd_pos == STROKA * STOLB )                          // Если находимся в самой последней позиции
          lcd_pos--;                                              // подумаем, что она предпоследняя
        lcd_pos -= lcd_pos % STROKA;
        goto_pos();
        break;
      case '\033':                                                // Обработка ESC-команд
          esc_cmd();
        break;
      case '\016':                                                // код '\000'
        c = 0;
      default:                                                    // собственно выводим символ на индикатор
        if (( lcd_pos % STROKA ) == 0 )                           // переходить ли на следующую строку?
          goto_pos();
        lcd_send_dat( c );
        if ( lcd_pos++ == STROKA * STOLB )                        // Позиции STROKA * STOLB и 0 эквивалентны!
          lcd_pos = 1;
        break;
    }
    previos = c_old;
  }
  else
    flag.redirect = OFF;
  return( c_old );
}
MrYuran
Цитата(rezident @ Mar 16 2009, 19:35) *
Я с вас дивлюся, мужики! Неужели пару страничек хелпа сложно прочитать? laughing.gif

Не, хелп читать это когда совсем ничего не выходит rolleyes.gif
а я залез в папку с примерами и увидел там putchar.c и printf.c - сделал а-ля и успокоился laughing.gif
CODE

/* PUTCHAR.C

The ANSI "putchar" function.

The putchar function writes the character c to the
output-stream pointed to by stream.
The function returns the character written. If an writing
error occurs the putchar shall return EOF.

$Revision: 1.3 $

Copyright 1986 - 1999 IAR Systems. All rights reserved.
*/


#include <stdio.h>

int putchar(int ch)
{
/*
put your own putchar-function here
*/
return ch;
}

/* - PRINTF.C -

The ANSI "printf" function.

$Revision: 1.3 $

Copyright 1986 - 1999 IAR Systems. All rights reserved.
*/

#include "stdarg.h"
#include "stdio.h"
#include "icclbutl.h"

static void put_one_char(char c, void *dummy)
{
putchar ©;
(void)dummy; /* Warning on this line OK (Optimized Away) */
}

int printf(const char *format, ...) /* Our main entry */
{
va_list ap;
int nr_of_chars;

va_start(ap, format); /* Variable argument begin */
nr_of_chars = _formatted_write(format, put_one_char, (void *) 0, ap);
va_end(ap); /* Variable argument end */
return nr_of_chars; /* According to ANSI */
}
tvilsa
Всем огромное спасибо.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.