Проблемы с передачей USART на PIC

Я пытаюсь отправить данные на SD-карту с PIC18f4580, но PIC не отправляет то, что должно быть.

связанные глобальные переменные:

unsigned char TXBuffer[128]; //tx buffer
unsigned char TXCurrentPos = 0x00; //tracks the next byte to be sent
unsigned char TXEndPos = 0x00; //tracks where new data should be put into the array

Я добавляю данные в буфер, используя следующую функцию:

void addToBuffer(char data){

    TXBuffer[TXEndPos] = data;
    TXEndPos++;
}

И помещаем данные из TXBuffer в TXREG со следующим прерыванием:

else if (PIR1bits.TXIF == 1){

    if((TXEndPos - TXCurrentPos) > 0){         // if there is data in the buffer
        TXREG = TXBuffer[TXCurrentPos];           // send next byte
        TXCurrentPos++;               // update to the new position
    }

Используя осциллограф, я вижу, что PIC отправляет 0x98, независимо от того, что я помещаю в буфер. На самом деле я никогда не помещал 0x98 в буфер.

Однако, если я заменю

TXREG = TXBuffer[TXCurrentPos];

с

TXREG = 0x55;

or

TXREG = TXCurrentPos;

тогда я получаю ожидаемые результаты, то есть PIC будет повторно отправлять 0x55 или считать от 0 соответственно.

Так почему же у PIC возникают проблемы с отправкой данных из массива, а в остальное время все нормально? Я подчеркну, что передача обрабатывается в прерывании, потому что я чувствую, что это корень моей проблемы.

РЕДАКТИРОВАТЬ: Это циклический буфер в том смысле, что TXEndPos и ​​TXCurrentPos возвращаются к 0, когда они достигают 127. Я также отключаю прерывание передачи, когда TXEndPos - TXCurrentPos == 0, и снова включаю его при добавлении данных в буфер. Действительно, мой код работает полностью так, как ожидалось, в том смысле, что если я добавлю 13 символов в TXBuffer в main, мой PIC передаст 13 символов, а затем остановится. Проблема в том, что они всегда одного и того же (неправильного) символа — 0x98.

EDIT2: более полные функции здесь: http://pastebin.com/MyYz1Qzq


person John Moffitt    schedule 19.09.2010    source источник
comment
Вы можете попробовать задать этот же вопрос на chiphacker.com, там много экспертов по картинкам.   -  person SingleNegationElimination    schedule 20.09.2010
comment
Маловероятно, что SD-карта хочет управляться асинхронным последовательным потоком, генерируемым UART. Вы уверены, что не хотите использовать вместо этого SPI?   -  person RBerteig    schedule 20.09.2010
comment
Вероятно, будет легче ответить, если вы опубликуете еще немного соответствующего кода и объясните более подробно, что вы пытаетесь сделать.   -  person Guy Sirton    schedule 20.09.2010
comment
@RBerteig: Да, я уверен @Guy: Я поработаю над устранением вопроса.   -  person John Moffitt    schedule 20.09.2010
comment
Функция в pastebin имеет TXREG = TXBuffer[TXEndPos];, а ваш код, размещенный здесь, имеет TXREG = TXBuffer[TXCurrentPos];   -  person pmg    schedule 20.09.2010
comment
@pmg: Это было результатом того, что я попробовал альтернативные строки, перечисленные выше, и перепечатал старую строку по памяти. Хотя это завело нас в тупик на несколько минут, это не является причиной нашей основной проблемы.   -  person John Moffitt    schedule 20.09.2010
comment
Это не основная проблема, но даже на PIC беззнаковый символ составляет 8 бит. Он переносится на 255, а не на 127. Ни показанный здесь код, ни код в pastebin не показывают никаких попыток заставить ++TXCurrentPos действовать по модулю 128.   -  person RBerteig    schedule 20.09.2010


Ответы (3)


Возможно, TXBuffer на самом деле не содержит данных, о которых вы думаете? Может быть, вы не вызываете addToBuffer или вызываете его не в то время или с неправильным параметром?

Вы можете попробовать что-то подобное в обработчике прерываний:

TXBuffer[TXCurrentPos] = TXCurrentPos;
TXREG = TXBuffer[TXCurrentPos];
TXCurrentPos++;

Просто чтобы доказать себе, что вы можете читать и писать в TXBuffer и отправлять это в USART.

Также попробуйте:

TXREG = TXEndPos;

Чтобы увидеть, соответствует ли это вашим ожиданиям (= длина вашего сообщения).

Я предполагаю, что есть какой-то другой код, который мы здесь не видим, который заботится о запуске передачи. Также предполагается, что это делается для каждого сообщения, а позиция сбрасывается между сообщениями, т.е. это не должен быть циклический буфер.

РЕДАКТИРОВАТЬ: На основе недавно опубликованного кода: вам не нужно запускать передатчик, записывая первый байт вашего буфера в TXREG? Что я обычно делаю, так это разрешаю прерывание и записываю первый байт в регистр передачи, и быстрый взгляд на таблицу данных, кажется, указывает на то, что вам нужно сделать. Другое дело, что я до сих пор не понимаю, как вы обеспечиваете переход от 127 к 0?

Кроме того, кажется, что ваш main() внезапно заканчивается, где выполнение продолжается после завершения main?

person Guy Sirton    schedule 19.09.2010
comment
Я уже пробовал TXREG = TXEndPos и ​​получил ожидаемый результат, длину моего сообщения. Попытка записать в TXBuffer, а затем прочитать из TXBuffer не сработала; У меня такой же характер, как и у меня. - person John Moffitt; 20.09.2010
comment
Возможно, TXBuffer не отображается в нужное место в памяти. Вы используете компилятор MPLAB C? Попробуйте поставить #pragma udata TXBuffer перед объявлением TXBuffer. Также проверьте все настройки, чтобы убедиться, что они соответствуют вашему PIC. Я думаю, что должен быть сценарий компоновщика, специфичный для этого PIC. Еще одна вещь, которую стоит попробовать, — запустить симулятор. - person Guy Sirton; 20.09.2010

Есть много вещей, о которых вы не заботитесь. TXBuffer должен быть кольцевым буфером. После того, как вы увеличите TXEndPos до 127, вам нужно вернуть его обратно к 0. То же самое для TXCurrrentPos. Это также влияет на тест, чтобы увидеть, есть ли что-то в буфере, тест > 0 недостаточно хорош. Общий совет доступен здесь.

person Hans Passant    schedule 19.09.2010
comment
Это не должен быть циклическим буфером. Это зависит от того, что хочет сделать ОП. Читая код, кажется, что он хочет настроить передачу одного сообщения размером ‹128 байт. - person Guy Sirton; 20.09.2010

Ваш код неполный, но он выглядит неправильно: что произойдет, если нечего отправлять? Вы, кажется, не загружаете TXREG, так зачем что-то передавать, будь то 0x98 или что-то еще?

Как это обычно делается, когда используется такая архитектура кода, это выключать TXIE, если нечего отправлять (в части else процедуры IRQ), и безоговорочно включать ее в конце функции addToBuffer (поскольку тогда вы точно знаете, что есть хотя бы один символ для отправки).

Кроме того, вы должны проверить TXEndPos и TXCurrentPos на равенство напрямую, так как это позволит вам очень легко использовать кольцевой буфер, добавив две операции по модулю.

person Samuel Tardieu    schedule 19.09.2010
comment
Я позаботился обо всех этих заботах. Я отредактировал свой пост, чтобы решить их. Я просто пытался сделать свой вопрос как можно короче и вырезал множество элементов управления для вещей, которые, по моему мнению, не применимы к моей проблеме. :П - person John Moffitt; 20.09.2010