|
|
  |
Непонятное поведение PIC16F690 |
|
|
|
Jul 7 2008, 11:12
|
Участник

Группа: Участник
Сообщений: 71
Регистрация: 10-03-07
Пользователь №: 26 038

|
Здравствуйте. Столкнулся с непонятным поведение PIC16F690. Имеется следующий код (только часть с непонятным поведением): Файл Main.asm: Код .... EXTERN UARTHnd EXTERN InitADC,ResetADC GLOBAL MainLoop,InitMCU
Reset: CODE GOTO InitMCU
Int: CODE GOTO UARTHnd Main: CODE
InitMCU: INTERRUPT_OFF CALL InitSFR CALL InitADC ;отправляем что-нибудь по uart-у для проверки работоспособности ;---------------------------------------------- BANKSEL TXREG MOVLW 0xAA MOVWF TXREG WT1: BTFSS PIR1,TXIF GOTO WT1 ;----------------------------------------------
MOVLW cINTCON MOVWF INTCON MainLoop: CALL StartTimeOut CALL UpDateADC WaitTimeOut: BANKSEL PIR1 BTFSS PIR1,TMR1IF GOTO WaitTimeOut GOTO MainLoop
StartTimeOut: ..... RETURN
InitSFR: .... RETURN END Файл CMD.asm Код ... EXTERN MainLoop GLOBAL UARTHnd ;нужный буду топом GenRegs: UDATA_OVR R6: RES 1 R5: RES 1 R4: RES 1 R3: RES 1 R2: RES 1 R1: RES 1 R0: RES 1
;нужный буду топом UARTData: UDATA Temp: RES d'1' Counter: RES d'1' NBytes: RES d'1' CmdBuf RES MAX_CMD_LENGTH ChekSum: RES d'2'
Interface: CODE
;Обработчик прерываний от UART, возникающего при получении очередного байта UARTHnd: BANKSEL RCREG MOVF RCREG,W MOVWF TXREG WT: BTFSS PIR1,TXIF GOTO WT RETFIE END Файл Comp.asm Код ... GLOBAL InitADC,ResetADC,SetGain,UpDateADC,WrByteADC,WrCommReg .... Comp: CODE
; Description: Отправка байта на АЦП WrByteADC: BANKSEL ADC_CS_PORT BCF ADC_CS SEL_BANK0 MOVWF R3;отправляемые данные MOVLW d'8' MOVWF R2;кол-во отправляемых бит
WBAL0: ;цикл отправки бит
BANKSEL ADC_SCLK_PORT BCF ADC_SCLK SEL_BANK0 RLF R3,F
;ДОЛЖНО БЫТЬ (В этом случае начинаются глюки) ;------------------------------------------------------------ ;BANKSEL ADC_DIN_PORT ;BCF ADC_DIN ;BTFSC STATUS,C ;BSF ADC_DIN ;------------------------------------------------------------
;ТАК РАБОТАЕТ (Хотя это форменный изврат) ;------------------------------------------------------------ BANKSEL ADC_DIN_PORT BCF ADC_DIN BTFSC STATUS,C
GOTO tmp tmp: BSF ADC_DIN ;------------------------------------------------------------
BANKSEL ADC_SCLK_PORT BSF ADC_SCLK
SEL_BANK0 DECFSZ R2,F GOTO WBAL0 BANKSEL ADC_CS_PORT BSF ADC_CS RETURN
;Инициализация АЦП InitADC: INTERRUPT_OFF CALL ResetADC WR_CLOCK_REG MOVLW b'00010010' CALL WrByteADC CALL SetGain RETURN .... Глюк заключается в следующим, если восстановить подпрограмму WrByteADC согласно приведенным, в ней комментариям, то в главной программе (Main) при попытке отправить байт по UART-у вместо 0xAA приходит, например, 0xFE (или еще что-нибудь, но не то что хотим). В обработчике прерывания от UART-а также вместо отправки принятого байта отправляется полная чушь. Подскажить в каком направлении искать правду.
|
|
|
|
|
Jul 7 2008, 14:10
|

Ambidexter
    
Группа: Свой
Сообщений: 1 589
Регистрация: 22-06-06
Из: Oxford, UK
Пользователь №: 18 282

|
Цитата(Grigorij @ Jul 7 2008, 10:12)  Столкнулся с непонятным поведение PIC16F690. Имеется следующий код (только часть с непонятным поведением) Код UARTHnd: BANKSEL RCREG MOVF RCREG,W MOVWF TXREG WT: BTFSS PIR1,TXIF GOTO WT RETFIE 1) При работе с UARТ по прерываниям не надо опрашивать флаг TXIF, иначе может быть непредсказуемое поведение. 2) Если в прерывании играетесь со статус-регистром и W, надо их сохранять и восстанавливать в конце прерывания, иначе будет непредсказуемое поведение. Цитата(Grigorij @ Jul 7 2008, 10:12)  Глюк заключается в следующим, если восстановить подпрограмму WrByteADC согласно приведенным, в ней комментариям, то в главной программе (Main) при попытке отправить байт по UART-у вместо 0xAA приходит, например, 0xFE (или еще что-нибудь, но не то что хотим). В обработчике прерывания от UART-а также вместо отправки принятого байта отправляется полная чушь. Подскажите в каком направлении искать правду. 3) Добейтесь устойчивой передачи по уарту в режиме опроса, а уж потом переходите к прерываниям. А вообще, если надо передавать одиночные байты, то лучше делать передачу по опросу: опросил флаг, не готово - подождал, готово - толкнул байт в регистр данных и ушёл делать другие дела. 4) Странно, что вам надо байты на ацп передавать, а данные с ацп как бы и не нужны. 5) Зачем так много играться с выбором банков памяти?
--------------------
Делай сразу хорошо, плохо само получится
|
|
|
|
|
Jul 8 2008, 04:30
|
Участник

Группа: Участник
Сообщений: 71
Регистрация: 10-03-07
Пользователь №: 26 038

|
Цитата(=GM= @ Jul 7 2008, 18:10)  1) При работе с UARТ по прерываниям не надо опрашивать флаг TXIF, иначе может быть непредсказуемое поведение. Исправление не помогло. Цитата(=GM= @ Jul 7 2008, 18:10)  2) Если в прерывании играетесь со статус-регистром и W, надо их сохранять и восстанавливать в конце прерывания, иначе будет непредсказуемое поведение.
3) Добейтесь устойчивой передачи по уарту в режиме опроса, а уж потом переходите к прерываниям. А вообще, если надо передавать одиночные байты, то лучше делать передачу по опросу: опросил флаг, не готово - подождал, готово - толкнул байт в регистр данных и ушёл делать другие дела. В том то все и дело, что если я убираю подпрограмму записи байтов в АЦП (WrByteADC), то UART начинает работает как часы. При этом WrByteADC, в приведенном примере, вызывается только один раз в начале программы. Т.к. все остальное время программа ждет прерывания от UART и выдает принятые данные, то STATUS и WREG я не стал сохранять. Цитата(=GM= @ Jul 7 2008, 18:10)  4) Странно, что вам надо байты на ацп передавать, а данные с ацп как бы и не нужны. Это еще впереди  . Цитата(=GM= @ Jul 7 2008, 18:10)  5) Зачем так много играться с выбором банков памяти? Здесь я просто промолчу  2 xemul: А что подразумевается под "если UARTHnd живет далеко от Int"? Может имеется в виду, что UARTHnd будет находится на другой странице? Если так, то вся программа находит на одной странице и, насколько я знаю, при вызове GOTO и CALL никаких манипуляций с PCLATH делать не надо (таблицы я не рассматриваю).
|
|
|
|
|
Jul 8 2008, 10:14
|

Ambidexter
    
Группа: Свой
Сообщений: 1 589
Регистрация: 22-06-06
Из: Oxford, UK
Пользователь №: 18 282

|
Цитата(Grigorij @ Jul 8 2008, 03:30)  Исправление не помогло. В том то все и дело, что если я убираю подпрограмму записи байтов в АЦП (WrByteADC), то UART начинает работает как часы. При этом WrByteADC, в приведенном примере, вызывается только один раз в начале программы. Т.к. все остальное время программа ждет прерывания от UART и выдает принятые данные, то STATUS и WREG я не стал сохранять 1) Исправление не помогло и не поможет, поскольку вы не используете прерывание. По крайней мере, в том тексте программы, что я видел. 2) Всё остальное время ваша программа не ждет прерывания от UART, а находится в цикле mainloop, вызывая поочередно StartTimeOut и UpDateADC, текст которой вы, кстати, не показали. 3) Биты выбора банка находятся в STATUSе, если вы его меняете в прерывании, то надо сохранять на входе и восстанавливать на выходе, это закон, не понимаю, чего здесь упираться. Также и с WREG. 4) Давайте посмотрим на все ваши назначения для ADC_CS_PORT, ADC_CS и т.д. 5) Изменения в WrByteADC означают всего-навсего задержку в два МЦ. Вы уверены в правильности формирования временной диаграммы? Какой ацп вы используете? Почему бы вместо программного обмена не использовать SSP модуль?
--------------------
Делай сразу хорошо, плохо само получится
|
|
|
|
|
Jul 8 2008, 10:37
|
    
Группа: Свой
Сообщений: 1 928
Регистрация: 11-07-06
Пользователь №: 18 731

|
Цитата(Grigorij @ Jul 8 2008, 08:30)  ... А что подразумевается под "если UARTHnd живет далеко от Int"? Может имеется в виду, что UARTHnd будет находится на другой странице? И это тоже. Попадая в прерывание с PCLATH & 0x18 != high(UARTHnd) & 0x18, на какую страницу Вы отправитесь по goto UARTHnd? Цитата Если так, то вся программа находит на одной странице и, насколько я знаю, при вызове GOTO и CALL никаких манипуляций с PCLATH делать не надо (таблицы я не рассматриваю). Нравится заботливо и загодя раскладывать для себя, любимого, грабельки? Вперед... W и STATUS Вам необходимо сохранять по любому, т.к. Вы их модифицируете в прерывании.
|
|
|
|
|
Aug 7 2008, 11:52
|
Участник

Группа: Участник
Сообщений: 33
Регистрация: 3-09-06
Из: SPb
Пользователь №: 20 040

|
Цитата Глюк заключается в следующим, если восстановить подпрограмму WrByteADC согласно приведенным, в ней комментариям, то в главной программе (Main) при попытке отправить байт по UART-у вместо 0xAA приходит, например, 0xFE (или еще что-нибудь, но не то что хотим). В обработчике прерывания от UART-а также вместо отправки принятого байта отправляется полная чушь.
Подскажить в каком направлении искать правду. Проверь банки, скорей всего передаешь по юарту значение из соседнего банка.
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|