Хостинг портала RFpro.ru: Московский хостер Профессиональный ХОСТИНГ на базе Linux x64 и Windows x64 РАССЫЛКИ ПОРТАЛА RFPRO.RU Лучшие эксперты данной рассылки Номер выпуска: | 1389 | Дата выхода: | 01.12.2010, 08:00 | Администратор рассылки: | Лысков Игорь Витальевич (Старший модератор) | Подписчиков / экспертов: | 221 / 67 | Вопросов / ответов: | 2 / 2 | Вопрос № 180942: Здравствуйте, уважаемые эксперты! Прошу Вас помочь с решением следуюшей задачи: - написать программу в среде MPLab для микроконтроллера PIC16F84. Требуется последовательно выводить числа от 0 до максимально возможного числа с использованием таймер... Вопрос № 180947: Здравствуйте, уважаемые эксперты! Прошу Вас ответить на следующий вопрос: Здравствуйте еще раз, помоги те пожалуйста с решением задачи, связанную с сопроцессорами "Рассчитать и вывести значение выражения, при заданных пользователем значени... Вопрос № 180942: Здравствуйте, уважаемые эксперты! Прошу Вас помочь с решением следуюшей задачи: - написать программу в среде MPLab для микроконтроллера PIC16F84. Требуется последовательно выводить числа от 0 до максимально возможного числа с использованием таймера прерываний на индикатор. Прилагаю блок - схему, по которой пишется программа с точностью до обозначений (но в ней чего-то не хватает). Из этой блок - схемы удалять элементы нельзя и переобозначать переменные тоже. Однако, насколько я понимаю, необходимо добавить блок - схемы некоторых подпрограмм. Вот ссылка:
blok_shema.pdf (103.6 кб)
К ответу прошу также приложить и блок - схему с ДОПОЛНЕНИЯМИ! Под индикатором, на который последовательно выводятся числа, понимается следующий приборчик:

Система команд микроконтроллера PIC16F84 такова :


Спасибо за Ваш труд!
Отправлен: 26.11.2010, 00:09 Вопрос задал: Dmitry (Посетитель) Всего ответов: 1 Страница вопроса » Отвечает Лысков Игорь Витальевич (Старший модератор) : Здравствуйте, Dmitry! Вот, накидал программу. Хотелось бы узнать, рабочая ли она... Потом добавлю, чего не хватает.
Код: LIST p=16F84 #include <p16f84.inc>
; Биты регистра PORTB DAT EQU 04h ; бит данных SYN EQU 05h ; бит синхронизации
CBLOCK 0CH ; блок рабочих регистров X WAIT W1 W2 W3 CNT1 CNT2 W_TEMP STATUS_TEMP ENDC
org 00h ; начало исполняемого кода GOTO START
org 04h ; программа обработки прерываний MOVWF W_TEMP MOVF STATUS,W MOVWF STATUS_T EMP
CLRF TMR0 ;очистка таймера BCF INTCON,T0IF ;сброс флага прерывания
COMF WAIT,F
MOVF STATUS_TEMP,W SWAPF W_TEMP,F SWAPF W_TEMP,W retfie
; Основная программа START ; Инициализация PORTB MOVLW B'11001111' ; настройка порта В
BSF STATUS,RP0 ; выбор банка 1 MOVWF TRISB ; установка RB4, RB5 на вывод
MOVLW B'01110010' MOVWF OPTION_REG
BCF STATUS,RP0 ; выбор банка 0 ; BSF PORTB,DAT ; установка битов DAT, SYN BSF PORTB,SYN ; в регистр PORTB
CLRF X ;X = 0 CLRF WAIT ;WAIT = 0
CLRF TMR0 MOVLW B'10100000' MOVWF INTCON
MAIN ;основной цикл BTFSS WAIT,0 GOTO MAIN
CALL VYVOD ;рисуем X
COMF WAIT,F
INCF X,F GOTO MAIN
VYVOD MOVF X,W MOVWF W1
MOVLW 4 MOVWF CNT1 DIGITS MOVLW 10 CALL DIVIDE CALL CODING CALL OUT
DECFSZ CNT1,F ; по всем 4 цифрам GOTO DIGITS
RETURN
;============================================= ; Преобразование BCD -> 7 сегментный код ; получаем в W сегменты индикатора ; 0 - горит ;============================================= CODING addwf PCL,F ; W + PC -> PC retlw b'11000000' ; ..FEDCBA = '0' retlw b'11111001' ; .....CB. = '1' retlw b'10100100' ; .G.ED.BA = '2' retlw b'10110000' ; .G..DCBA = '3' retlw b'10011001' ; .GF..CB. = '4' retlw b'10010010' ; .GF.DC.A = '5' retlw b'10000010' ; .GFEDC.A = '6' retlw b'11111000' ; .....CBA = '7' retlw b'10000000' ; .GFEDCBA = '8' retlw b'10010000' ; .GF.DCBA = '9'
; Подпрограмма вывода OUT MOVWF W2 ; сохраним в W2 MOVLW D'8' ; 8 бит MOVWF CNT2 ; в счетчик CNT2 SEGMENTS BCF P ORTB,DAT ; установка в 0 RB4 (чтобы горело) BTFSC W2,0 ; если 0 бит в регистре W2 = 0, то пропускаем BSF PORTB,DAT ; команду, если нет, то установка RB4 в 1 (чтобы потухло)
; синхронизация PORTB BCF PORTB,SYN BSF PORTB,SYN
RRF W2,F ; сдвиг вправо, через перенос DECFSZ CNT2,F ; по всем 8 битам GOTO SEGMENTS ; переход на метку SEGMENTS
RETURN ; возврат из подпрограммы
DIVIDE MOVWF W2 ; сохраним в W2 MOVF W1,W MOVWF W3 ; сохраним в W3 MOVF W2,W CLRF W1 SUBLOOP SUBWF W3,F BTFSS STATUS,C GOTO DIVRET INCF W1,F GOTO SUBLOOP DIVRET ADDWF W3,W
RETURN
END
----- Люби своего ближнего, как самого себя Ответ отправил: Лысков Игорь Витальевич (Старший модератор) Ответ отправлен: 26.11.2010, 17:54 Номер ответа: 264350 Украина, Кировоград Тел.: +380957525051 ICQ # 234137952 Mail.ru-агент: igorlyskov@mail.ru Вам помог ответ? Пожалуйста, поблагодарите эксперта за это! Как сказать этому эксперту "спасибо"? | Отправить SMS #thank 264350 на номер 1151 (Россия) | Еще номера » | Вопрос № 180947: Здравствуйте, уважаемые эксперты! Прошу Вас ответить на следующий вопрос: Здравствуйте еще раз, помоги те пожалуйста с решением задачи, связанную с сопроцессорами "Рассчитать и вывести значение выражения, при заданных пользователем значениях x и a." и пример:
Отправлен: 26.11.2010, 03:13 Вопрос задал: Алексей Патрин (Посетитель) Всего ответов: 1 Страница вопроса » Отвечает Лысков Игорь Витальевич (Старший модератор) : Здравствуйте, Алексей Патрин! Вот Вам программа... Считается все, как в формуле (без упрощений) ...
Код: .model tiny, C .data sX db 'Enter x: $' ;приглашения для ввода sA db 0ah,'Enter a: $' sY db 0ah,'Y = $' ;результат sAny db 0dh,0ah,'Press any key$'
x dq 0 ;переменные a dq 0
num db 32 ;буфер для ввода строки len db 0 String db 32 dup (0)
.code .386 .startup lea dx, sX mov ah, 9 int 21h ;ждем Х
lea dx, num mov ah, 0ah int 21h
call str2float ;преобразуем строку в double fstp x lea dx, sA mov ah, 9 int 21h ;ждем А
lea dx, num mov ah, 0ah int 21h
call str2float ;преобразуем строку в double fstp a
call calcY, offset a, offset x ;считаем по формуле
call float2str ;преобразуем в строку lea dx, sY mov ah, 9 int 21h lea dx, String ;выведем mov ah, 9 int 21h
lea dx, sAny mov ah, 9 int 21h ;ждем "any key"
mov ah, 8 int 21h mov ax, 4c00h int 21h
;експонента st=e^st exp proc fldl2e ;log(осн 2)e->st fmulp ;st(1)*log(осн 2)e->st fld st ;x*log[2]e->st(1) frndint ;округляем st до целого fsub st(1),st ;st(1)-=st fxch ;st(1)<->st f2xm1 ;st=(2 в степени st) - 1 fld1 ;1->st fadd ;st+=1 fscale ;exp = st * (2 в степени st(1)) fstp st(1) ;чтобы убрать значение из st(1) ret exp endp
;считаем по формуле y=(3*4 +5*6-ae^x)/(7/2+4/3+12/3)*(16/2)*3*6*cos(a/x) calcY proc pa:word, px:word local c2:word, c3:word, c4:word, c5:word, c6:word, c7:word, c12:word, c16:word uses di, si mov di, pa ;адрес А mov si, px ;адрес Х mov c2, 2 ;константы mov c3, 3 mov c4, 4 mov c5, 5 mov c6, 6 mov c7, 7 mov c12, 12 mov c16, 16
fild c3 ;3 fimul c4 ;3*4 fild c5 ;5 fimul c6 ;5*6 faddp ;3*4+5*6 fld qword ptr [si] ;x call exp ;e^x fmul qword ptr [di] ;a*e^x fsubp st(1), st ;3*4+5*6-a*e^x
fild c7 ;7 fidiv c2 ;7/2 fild c4 ;4 fidiv c3 ;4/3 faddp ;7/2+4/3 fild c12 ;12 fidiv c3 ;12/3 faddp ;7/2+4/3+12/3
fdivp ;y=(3*4+5*6-a*e^x)/(7/2+4/3+12/3)
fimul c16 ;y*16 fidiv c2 ;y*16/2 fimul c3 ;y*16/2*3 fimul c6 ;y*16/2*3*6
fld qword ptr [di] ;a fdiv qword ptr [si] ;a/x fcos ;cos(a/x) fmulp ;y*16/2*3*6*cos(a/x) ret c alcY endp
;Преобразование строки в вещественное число в st сопроцессора str2float proc ;преобразование строки в вещественное число local ww:word ;для загрузки в сопроцессор local dcount:word ;число знаков после точки local wSign:word ;знак числа local c10:word ;10
fldz ;подготовим st=0 lea si, String ;числовая строка xor ax, ax ;0 mov dcount, ax ;число знаков после точки = 0 mov wSign, ax ;положительное mov c10, 10 ;10 s2fStart: ;цикл обхода незначащих стартовых пробелов lodsb cmp al, 0dh je s2fRet ;по концу строки - выход cmp al, ' ' je s2fStart ;на повтор cmp al, 9 je s2fStart cmp al, '-' jne s2fCompare ;все остальное - на анализ inc wSign ;по минусу - взводим признак минуса s2fNext: lodsb ;очередной символ s2fCompare: cmp al, '.' ;точка je s2fInc cmp al, '0' jb s2fSign ;все, что не цифры - конец числа cmp al, '9' ja s2fSign
and ax, 0fh ;иначе готовим разряд mov ww, ax ; для загрузки в сопроцессор cmp dcount , 0 ;если целая часть, то je s2fMul10 ; на умножение на 10 mov cx, dcount ;иначе делим dcount раз на 10 fild ww ; очередной разряд s2fdiv: fidiv c10 ;делим dcount раз loop s2fdiv faddp ;складываем разряд за точкой с формируемым числом s2fInc: inc dcount ;для точки только увеличиваем dcount jmp s2fNext ;пока не дойдем до конца
s2fMul10: ;целое число fimul c10 ;умножаем старое на 10 fiadd ww ;и прибавляем очередной разряд jmp s2fNext s2fSign: cmp wSign, 0 ;если bSign == 1 je s2fRet fchs ;то меняем знак s2fRet: ret str2float endp
;преобразование вещественного числа из st в строку по адресу String float2str proc local c10:word ;10 local wSign:word ;знак local dig:word ;буфер для извлечения целого из сопроцессора local sTemp:byte:64 ;временный буфер для строки
mov c10, 10 ;10 mov wSign, 0 ;пока считаем, что положительное lea di, sTemp ;здесь буде м формировать строку ftst ;Проверяем число fstsw ax ;флаги в ax sahf ;флаги в регистре флагов jnz f2s_notZero ;не 0 mov ax, '$0' ;если 0, то выводим 0 stosw jmp f2s_Ret ;на выход
f2s_notZero: ;не 0 jnc f2s_1 ;если отрицательное, inc wSign ; то помечаем минус fchs ; и оставляем модуль числа. ; Пояснение далее пойдёт на примере. ; ST(0) ST(1) ST(2) ST(3) ... ; Отделим целую часть от дробной. ; 73.25 ... f2s_1: fld1 ; 1 73.25 ... fld st(1) ; 73.25 1 73.25 ... ; Остаток от деления на единицу даст дробную часть. fprem ; 0.25 1 73.25 ... ; Если вычесть её из исходного числа, получится целая часть. fsub st(2), st ; 0.25 1 73 ... fxch st(2) ; 73 1 0.25 ... ; Сначала поработаем с целой частью. Считать количество цифр будем в CX. xor cx, cx ; Поделим целую часть на десять, f2s_2: fidiv c10 ; 7.3 1 0.25 ... fxch st(1) ; 1 7.3 0.25 ... fld st(1) ; 7.3 1 7.3 0.25 ... ; отделим дробную часть - очередную справа цифру целой части исходного числа,- fprem ; 0.3 1 7.3 0.25 ... ; от чатсного оставим только целую часть fsub st(2), st ; 0.3 1 7 0.25 ... ; и сохраним цифру fimul c10 ; 3 1 7 0.25 ... fistp dig ; 1 7 0.25 ... inc cx ; в стеке. push dig fxch st(1) ; 7 1 0.25 ... ; Так будем повторять, пока от целой части не останется ноль. ftst fstsw ax sahf jnz f2s_2 ; Теперь выведем её. f2s_3: pop ax ; Вытаскиваем очередную цифру, переводим её в символ и выводим. add al, 30h stosb ; И так, пока не выведем все цифры. loop f2s_3 ; 0 1 0.25 ... ; Итак, теперь возьмёмся за дробную часть, для начала проверив её существование. fstp st(0) ; 1 0.25 ... fxch st(1) ; 0.25 1 ... ftst fstsw ax sahf jz f2s_5 ; Если она всё- таки ненулевая, выведем точку lea ax, sTemp mov cx, di sub cx, ax sub cx, 63 neg cx mov al, '.' stosb ; Помножим дробную часть на десять f2s_4: fimul c10 ; 2.5 1 ... fxch st(1) ; 1 2.5 ... fld st(1) ; 2.5 1 2.5 ... ; отделим целую часть - очередную слева цифру дробной части исходного числа,- fprem ; 0.5 1 2.5 ... ; оставим от произведения лишь дробную часть fsub st(2), st ; 0.5 1 2 ... fxch st(2) ; 2 1 0.5 ... ; сохраним полученную цифру во временной ячейке fistp dig ; 1 0.5 ... ; и сразу выведем. mov ax, dig add al, 30h stosb ; Теперь, если остаток дробной части ненулевой fxch st(1) ; 0.5 1 ... ftst fstsw ax sahf ; и мы вывели менее cx цифр, продолжим loopnz f2s_4 ; 0 1 ... ; Итак, число выведено. Осталось убрать мусор из стека. f2s_5: fstp st(0) ; 1 ... fstp st(0) ; ... mov byte ptr [di], '$'
; и скопировать в буфер String lea si, sTemp lea di, String xor cx, cx ;длина c mp wSign, 0 ;проверим на знак je f2s_6 mov al, '-' ;отрицательное stosb f2s_6: lodsb stosb ;копируем 1 байт inc cx ;считаем cmp cx, 14 ;копируем только 14 байт !!! (если получится число ; с большим чем 14 байт знаков, то последние усекутся) je f2s_7 ;насильно закрываем $! cmp al, '$' jne f2s_6 ;копирование завершаем по $ dec cx ;отнимем 1 (посчитался $) f2s_7: mov byte ptr [di], '$' ;закроем $ (для случая обрезания) f2s_Ret: ret float2str endp
end
----- Люби своего ближнего, как самого себя Ответ отправил: Лысков Игорь Витальевич (Старший модератор) Ответ отправлен: 28.11.2010, 01:28 Номер ответа: 264366 Украина, Кировоград Тел.: +380957525051 ICQ # 234137952 Mail.ru-агент: igorlyskov@mail.ru
Оценка ответа: 5 Вам помог ответ? Пожалуйста, поблагодарите эксперта за это! Как сказать этому эксперту "спасибо"? | Отправить SMS #thank 264366 на номер 1151 (Россия) | Еще номера » | Оценить выпуск » Нам очень важно Ваше мнение об этом выпуске рассылки! Скажите "спасибо" эксперту, который помог Вам! Отправьте СМС-сообщение с тестом #thank НОМЕР_ОТВЕТА на короткий номер 1151 (Россия) Номер ответа и конкретный текст СМС указан внизу каждого ответа. Полный список номеров » * Стоимость одного СМС-сообщения от 7.15 руб. и зависит от оператора сотовой связи. (полный список тарифов) ** При ошибочном вводе номера ответа или текста #thank услуга считается оказанной, денежные средства не возвращаются. *** Сумма выплаты эксперту-автору ответа расчитывается из суммы перечислений на портал от биллинговой компании. |
Комментариев нет:
Отправить комментарий