Консультация № 182543
17.03.2011, 13:47
101.11 руб.
0 27 1
Здравствуйте, уважаемые эксперты! Прошу Вас помочь с решением следуюшей задачи:
- написать программу в среде MPLab для микроконтроллера PIC16F84.
Общая задача такова: в программу на компьютере вводятся 2 числа и операция между ними (например, 2+3), далее это отправляется на COM порт, к которому подключен микроконтроллер. Он принимает данные, выполняет требуемую операцию с этими числами, выводит результат на индикатор-семисегментик, а также отправляет этот результат обратно в COM порт, передавая его компьютеру. То есть это, своего рода, программа "калькулятор" ...

Просьба к Вам, уважаемые эксперты, помочь с решением той части задачи, которую выполняет микроконтроллер, то есть написать программу для микроконтроллера. Надеюсь на Вашу помощь!

p.s.: Только арифметические операции "+", "-", "*","/".

Обсуждение

давно
Посетитель
7438
7205
21.03.2011, 18:48
общий
Основная проблема не в, собственно, калькуляторе, а организации обмена.
Что далеко не просто, как хотелось бы, т.к. в PIC16F84 нет встроенного последовательного канала.
Надо все реализовывать программно. И надо потратить достаточно много времени, чтобы все это реализовать.
Посему, было бы неплохо, если бы Вы добавили оплату...
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
Неизвестный
21.03.2011, 19:12
общий
Адресаты:
Здравствуйте! Скажите, сколько необходимо доплатить?
давно
Посетитель
7438
7205
21.03.2011, 21:14
общий
Давайте остановимся на 100 .
Я начинаю работать над программой
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
давно
Посетитель
7438
7205
22.03.2011, 09:46
общий
Несколько вопросов...
1) Какова частота контроллера?
2) Параметры последовательного порта (Боды, число бит, стопов, четность) ?
3) CTS/RTS используются?
4) Было бы неплохо увидеть схему аппаратной части...
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
Неизвестный
22.03.2011, 15:19
общий
Здравствуйте!
1) 100 рублей доплатить к первоначальной стоимости, или это конечная цена?
2) тактовая частота контроллера, как написано в методичке, 0...10 Мгц;
3) параметры последовательного порта:
dcb.BaudRate = 9600; боды
dcb.ByteSize = 8; число бит
dcb.Parity = NOPARITY; чётность
dcb.StopBits = ONESTOPBIT; стопов
4) в нашей же методичке есть пример программы такой: "поочередные передача и прием байтов. Скорость обмена 9600 бот, длина данных 8 бит, контроль четности не используется." Думаю, именно в этом главная фишка нашей задачи. Только ее модернизировать для калькулятора. Я верно рассуждаю? Если да, то я пришлю весь код этой программы Вам.
давно
Посетитель
7438
7205
22.03.2011, 15:33
общий
1) Конечная цена
4) Методичку обязательно, с этого надо было начинать.
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
Неизвестный
22.03.2011, 15:39
общий
Адресаты:
Вот такой код:


давно
Посетитель
7438
7205
22.03.2011, 16:02
общий
Хм, а лучшего качества никак нельзя?
Ничего не видно...
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
Неизвестный
22.03.2011, 18:14
общий
Адресаты:
Игорь Витальевич, тут два варианта. Либо можно сохранить картинки у себя на компьютере и при увеличении все очень четко видно, либо только завтра буду перефотографировать каждую страницу отдельным фото...
давно
Посетитель
7438
7205
22.03.2011, 18:21
общий
Ок, жду завтра
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
Неизвестный
23.03.2011, 14:40
общий
Адресаты:
Здравствуйте! Вот такой код:







давно
Посетитель
7438
7205
23.03.2011, 14:43
общий
Ок.
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
давно
Посетитель
7438
7205
24.03.2011, 16:26
общий
это ответ
Здравствуйте, Dmitry!
Вот и программа, которая принимает три байта (два знаковых числа и код операции) по RS-232С,
считает, выдает на индикатор результат и передает результат обратно
Сделан минимальный контроль: код операции (1-4) и на деление на 0
Для вывода на монитор я воспользовался ранее написанной программой...
Пробуйте

[code h=200];Программа калькулятора
;Программа принимает от компьютера по каналу RS-232C три байта:
;первый операнд, второй операнд, код операции
;1 = +, 2 = -, 3 = *, 4 = /
;После чего считает, выводит на индикатор и передает обратно байт результата
;Проверяется код операции, деление на 0
;
;Параметры RS-232C:
;скорость 9600 бод, 1 стоп-бит, без контроля четности
;выдержки времени рассчитаны для цикла 1 мкс
;------------------------------------------------------
;Установка типа процессора
LIST P=16F84
;------------------------------------------------------
;Регистры специального назначения
STATUS EQU 03h ;регистр статуса
PORTB EQU 06h ;порт В
PCL EQU 02h ;регистр программного счетчика
;------------------------------------------------------
;Биты регистра STATUS
RP0 EQU 5h ;бит выбора страницы
Z EQU 2h ;номер бита Z в статусе
C EQU 0h ;номер бита С в статусе
;------------------------------------------------------
;Управляющие регистры портов ввода-вывода
TRISB EQU 6h
;------------------------------------------------------
;ОЗУ
;рабочие регистры для приема/передачи
WORK1 EQU 0Eh
WORK2 EQU 0Fh
WORK3 EQU 10h
;аргументы калькулятора
ARG1 EQU 11h
ARG2 EQU 12h
;рабочие регистры для вывода на дисплей
CNT_1 EQU 13h ;счетчики
CNT_2 EQU 14h
CNT_3 EQU 15h
CNT_4 EQU 16h
W1 EQU 17h ;временные регистры для расчетов
W2 EQU 18h
W3 EQU 19h
;------------------------------------------------------
;биты регистра PORTB
DAT EQU 4h ;бит данных (порт В)
SYN EQU 5h ;бит синхронизации (порт В)
RS232TX EQU 6h ;передатчик RS-232C
RS232RX EQU 7h ;приемник RS-232C
;
;------------------------------------------------------
; Программа
;------------------------------------------------------
ORG 0h ;начало кода
GOTO START
ORG 4h ;программа обработки прерываний
RETFIE ;отсутствует
;
START
BSF STATUS,RP0 ;настройка порта PORTB
MOVLW B'10001111' ;установка RB4-RB6 на вывод
MOVWF TRISB
BCF STATUS,RP0

;установка битов в 1
BSF PORTB,DAT ;бит данных индикации
BSF PORTB,SYN ;бит синхро индикации
BSF PORTB,RS232TX ;передатчик RS-232С

;основной цикл программы
LOOP1 ;принимаем первый аргумент
BTFSC PORTB,RS232RX ;ожидание старт-бита
GOTO LOOP1 ; принимаемых данных
CALL RX232 ;прием байта в WORK1 и в аккумулятор
MOVWF ARG1 ;сохраним в ARG1

LOOP2 ;принимаем второй аргумент
BTFSC PORTB,RS232RX ;ожидание старт-бита
GOTO LOOP2 ; принимаемых данных
CALL RX232 ;прием байта в WORK1 и в аккумулятор
MOVWF ARG2 ;сохраним в ARG2

LOOP3 ;принимаем код операции
BTFSC PORTB,RS232RX ;ожидание старт-бита
GOTO LOOP3 ; принимаемых данных
CALL RX232 ;прием байта в WORK1 и в аккумулятор

;определимся с операцией
;результат всех операций будет в ARG1
DECFSZ WORK1,1 ;1 = +
GOTO CMPSUB ;проверим на -
CALL PLUS ;отработаем +
GOTO OUTPUT ;на вывод результата
CMPSUB
DECFSZ WORK1,1 ;2 = -
GOTO CMPMUL ;проверим на *
CALL MENUS ;отработаем -
GOTO OUTPUT ;на вывод результата
CMPMUL
DECFSZ WORK1,1 ;3 = *
GOTO CMPDIV ;проверим на /
CALL MULT ;отработаем *
GOTO OUTPUT ;на вывод результата
CMPDIV
DECFSZ WORK1,1 ;4 = /
GOTO PRERR ;все остальное на вывод ошибки Err1
CALL DIVIDE ;отработаем /
GOTO TRANS ;на передачу (вывод на экран внутри DIVIDE)
PRERR ;вывод сообщения об ошибке
MOVLW D'1' ;1 - номер ошибки
CALL ERR ;Err1
CLRW ;вернем 0
GOTO TRANS ;на передачу
OUTPUT
CALL DISPLAY ;вывод знакового числа из ARG1 на дисплей
TRANS
CALL TX232 ;передача байта из ARG1
GOTO LOOP1 ;на повтор
;
PLUS ;ARG1 = ARG1 + ARG2
MOVFW ARG2
ADDWF ARG1,1
RETURN
;
MENUS ;ARG1 = ARG1 - ARG1
MOVFW ARG2
SUBWF ARG1,1
RETURN
;
MULT ;ARG1 = ARG1 * ARG2
MOVFW ARG1 ;проверим на равенство нулю операндов
ANDWF ARG2,0 ;если хоть один = 0, то и произведение = 0
BTFSC STATUS,Z ;проверяем бит нуля, если Z = 0, то ответ 0
GOTO MULTNEXT ;на умножение
CLRF ARG1 ;результат 0
RETURN
MULTNEXT ;умножаем, складывая ARG1 ARG2 раз
MOVFW ARG1 ;W = ARG1
CLRF ARG1 ;ARG1 - здесь будем накапливать сумму
MULTLOOP
ADDWF ARG1,1 ;ARG1 = ARG1 + W
DECFSZ ARG2,1 ;ARG2 раз
GOTO MULTLOOP
RETURN
;
DIVIDE ;ARG1 = ARG1 / ARG2
MOVFW ARG2 ;проверим на равенство нулю делителя
ANDWF ARG2,0 ;если = 0, то ошибка Err2
BTFSC STATUS,Z ;проверяем бит нуля, если Z = 0, то ошибка 2!
GOTO DIVNEXT ;на деление
MOVLW '2'
CALL ERR ;сообщение об ошибке
CLRF ARG1 ;возвращаем 0
RETURN
DIVNEXT ;для деления воспользуемся подпрограммой DIVISION
MOVFW ARG1 ;для чего запишем делимое
MOVWF W1 ;в W1
MOVFW ARG2 ;а делитель - в W
CALL DIVISION ;результат: W1 - частное, W - остаток
MOVFW W1 ;сохраним частное
MOVWF ARG1 ;в ARG1
CALL DISPLAY ;на дисплей
RETURN
;
DISPLAY ;вывод знакового числа ARG1 на дисплей
MOVLW d'3' ;3 цифры
MOVWF CNT_1 ;CNT_1 - счетчик цифр
MOVF ARG1,0 ;W = ARG1
BTFSS ARG1,7 ;проверяем старший бит - бит знака
GOTO POSITIVE ;ARG1.7 = 0 - >0
COMF ARG1,0 ;найдем модуль числа
ADDLW D'1' ; W = (not ARG1) + 1
POSITIVE:
MOVWF W1 ;W1 = W = ARG1

;цикл вывода десятичных знаков
M01 MOVLW d'10' ;будем делить W1 на 10 и получать в W остаток
CALL DIVISION ; от деления - очередной младший разряд
CALL CODE_SEG ;конвертируем число в сегментный код
CALL OUT_SEG ;зажигаем нужные сегменты
DECFSZ CNT_1,1 ;CNT_1 = CNT_1 - 1, если 0, то на RETURN
GOTO M01 ;иначе повторяем
;выведем знак числа
MOVLW D'10' ;пусто - для положительных
BTFSS ARG1,7 ;проверяем старший бит - бит знака
GOTO DISPSIGN ;>0 идем на вывод
MOVLW D'11' ;- для отрицательных
DISPSIGN
CALL CODE_SEG ;конвертируем число в сегментный код
CALL OUT_SEG ;зажигаем нужные сегменты
RETURN ;выход

;вывод цифры (отработка сегментов, заданных в регистре W)
OUT_SEG
MOVWF W2 ;W2 = W
MOVLW d'8'
MOVWF CNT_2 ;CNT_2 = 8 - число бит

;цикл по битам
M03 BCF PORTB,DAT ;установка в 0 RB4 (чтобы горело)
BTFSC W2,0 ;если 0 бит в регистре W2 = 0, то пропускаем
BSF PORTB,DAT ;команду, если нет, то установка RB4 в 1 (чтобы потухло)

; синхронизация PORTB
BCF PORTB,SYN
BSF PORTB,SYN

RRF W2,1 ;сдвиг вправо на 1 бит
DECFSZ CNT_2,1 ;по всем 8 битам
GOTO M03 ;повтор
RETURN

;деление W1 на W
;находим путем последовательного вычитания
;делителя из делимого
;результат: W1 - частное, W - остаток
DIVISION
MOVWF W2 ;сохраним W в W2, т.к. след команда его портит
MOVF W1,0 ;W = W1
MOVWF W3 ;W3 = W = W1 - делимое
MOVF W2,0 ;восстановим W = W2 - делитель
CLRF W1 ;W1 = 0 - частное, как количество вычитаний делителя

;цикл вычитания делителя из делимого
;вычитание заменяется сложением с кодом в дополнительном коде
;т.е. 5-2 = 5+0feh = 3 и С=1
; 1-2 = 1+0feh = 0ffh и C=0
;т.о., C=1 означает, что отнимается, а С=0 - нет

M04 SUBWF W3,1 ;W3 = W3 - W
BTFSC STATUS,C ;проверяем бит переноса, если C = 0, то на выход
GOTO M05 ;на инкремент частного
ADDWF W3,0 ;добавим лишний раз отнятый делитель, результат в W
RETURN ;имеем в W1 частное, а W - остаток

M05 INCF W1,1 ;считаем отнятые делители
GOTO M04 ;продолжаем

;кодировка кода на иникатор
;на входе W = 0-9
;10 - знак пусто (для положительных)
;11 - знак минус (для отрицательных)
;12 - символ 'E' (для сообщения Err)
;13 - символ 'r' (для сообщения Err)
;на выходе код
CODE_SEG
ADDWF PCL,1 ;переход на адрес следующей команы + содержимое W
RETLW b'00000011' ;0
RETLW b'10011111' ;1
RETLW b'00100101' ;2
RETLW b'00001101' ;3
RETLW b'10011001' ;4
RETLW b'01001001' ;5
RETLW b'01000001' ;6
RETLW b'00011111' ;7
RETLW b'00000001' ;8
RETLW b'00001001' ;9
RETLW b'11111111' ;ничего не горит (для +)
RETLW b'11111101' ;-
RETLW b'01100001' ;E
RETLW b'11110101' ;r

ERR ;вывод сообщения об ошибке
;в W число - код ошибки
CALL CODE_SEG ;конвертируем число в сегментный код
CALL OUT_SEG ;зажигаем нужные сегменты
MOVLW D'13' ;r
CALL CODE_SEG ;конвертируем число в сегментный код
CALL OUT_SEG ;зажигаем нужные сегменты
MOVLW D'13' ;r
CALL CODE_SEG ;конвертируем число в сегментный код
CALL OUT_SEG ;зажигаем нужные сегменты
MOVLW D'12' ;E
CALL CODE_SEG ;конвертируем число в сегментный код
CALL OUT_SEG ;зажигаем нужные сегменты
RETURN

;----------------------------------------------------
;Подпрограммы приема-передачи
;----------------------------------------------------
;Подпрограмма приема байта в регистр WORK1 и W по RS-232C
RX232
CLRF WORK1 ;очистка приемника байта
;
MOVLW D'49' ;пауза 148 мкс для выхода
MOVWF WORK3 ;примерно на середину интервалов
R00
DECFSZ WORK3,1 ;принимаемых битов
GOTO R00
;
MOVLW 8h ;счетчик принимаемых битов
MOVWF WORK2
R01
RRF WORK1,1 ;сдвиг приемника байта
BTFSS PORTB,RS232RX ;принятый бит равен 1 ?
GOTO R02 ;нет!
BSF WORK1,7 ;да! установить очередной бит в 1
GOTO R03 ;приемника байта
R02
NOP ;задержка, выравнивающая время приема 0 и 1
BCF WORK1,7 ;принятый бит = 0
;
R03
MOVLW D'31' ;пауза 95 мкс, дополняющая время
MOVWF WORK3 ;приема бита до 104 мкс
R04
DECFSZ WORK3,1
GOTO R04
NOP
;
DECFSZ WORK2,1 ;по всем битам
GOTO R01
;
MOVFW WORK1 ;W = WORK1
RETURN

;подпрограмма передачи байта из регистра ARG1 по RS-232C.
TX232
BCF PORTB,RS232TX ;передача старт-бита
MOVLW D'33' ;пауза 100 мкс, дополняющая время
MOVWF WORK2 ;передачи старт-бита до 104 мкс
W00
DECFSZ WORK2,1
GOTO W00
;
MOVLW 8h ;будем передавать 8 бит
MOVWF WORK2
W01
BTFSS ARG1,0 ;очередной бит = 1 ?
GOTO W02 ;-нет!
BSF PORTB,RS232TX ;-да!
GOTO W03
W02

BCF PORTB,RS232TX ;бит = 0
NOP ;задержка, выравнивающая время передачиа 0 и 1
W03
RRF ARG1,1 ;сдвиг передаваемого байта для передачи следующего бита
;
MOVLW D'31' ;пауза 95 мкс, дополняющая время
MOVWF WORK3 ;приема бита до 104 мкс
W04
DECFSZ WORK3,1
GOTO W04
NOP
;
DECFSZ WORK2,1 ;по всем битам
GOTO W01
;
BSF PORTB,RS232TX ;передача стоп-бита
MOVLW D'34' ;пауза, дополняющая время
MOVWF WORK3 ;передачи стоп-бита до 104 мкс
W05
DECFSZ WORK3,1
GOTO W05
RETURN

END
[/code]
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
Неизвестный
24.03.2011, 16:49
общий
Адресаты:
Здравствуйте, спасибо, в среду попаду в аудиторию, проверю работу !
давно
Посетитель
7438
7205
24.03.2011, 16:54
общий
А программа для компа есть? Без нее же не проверишь...
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
Неизвестный
24.03.2011, 17:01
общий
Адресаты:
В процессе написания...
Неизвестный
30.03.2011, 14:26
общий
Адресаты:
Здравствуйте! НЕ получается...
Вводим любые два числа и операцию, в любом случае контроллер выдает результат "Err1"...
давно
Посетитель
7438
7205
30.03.2011, 14:50
общий
Какие байты передаются?
Должно быть:
1) первый операнд
2) второй операнд
3) код операции (01h = +, 02h = -, 03h = *, 04h = /)
Err1 говорит о некорретном коде операции. Может передавали символы '1' = 31h и т.п.?
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
Неизвестный
30.03.2011, 16:53
общий
Адресаты:
Упс, обнаружился косячек в компьютерной части программы, на днях проверю работу вновь, скажу Вам!
давно
Старший Модератор
31795
6196
30.03.2011, 18:27
общий
Выложите код РС-программы.
Об авторе:
Мне безразлично, что Вы думаете о обо мне, но я рад за Вас - Вы начали думать.

Неизвестный
02.04.2011, 12:01
общий
Адресаты:
Здравствуйте, Константин Николаевич! Всё уже работает, поэтому неактуально выкладывать код!
Неизвестный
02.04.2011, 12:02
общий
Адресаты:
Здравствуйте, Игорь Витальевич! Всё работает на ОТЛИЧНО! Спасибо Вам огромное! Чрезвычайно благодарен за Вашу помощь! Счастья Вам и здоровья!
Неизвестный
20.04.2011, 21:04
общий
Адресаты:
Здравствуйте, Игорь Витальевич! Вновь обращаюсь к Вам за помощью. Помогите, пожалуйста, составить блок-схему написанной Вами программы. И добавьте к сообщению, сколько нужно доплатить!
давно
Посетитель
7438
7205
21.04.2011, 00:35
общий
Хорошо, завтра сделаю...
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
давно
Посетитель
7438
7205
24.04.2011, 01:54
общий
Уф, я аж умаялся, пока нарисовал эти блок-схемы...
С Вас "спасибо"...
181543_block-sch.doc (93.0 кб)
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
Неизвестный
24.04.2011, 18:57
общий
Адресаты:
Спасибо Вам огромное, Игорь Витальевич! Отправил 55 рублей через "спасибо". достаточно?
давно
Посетитель
7438
7205
24.04.2011, 22:05
общий
Да, конечно. Для меня более важно то, что Вы цените чужой труд...
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
Форма ответа