С Новым годом! Форум программистов, компьютерный форум, киберфорум
Микроконтроллеры
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.75/4: Рейтинг темы: голосов - 4, средняя оценка - 4.75
0 / 0 / 0
Регистрация: 04.05.2023
Сообщений: 8
1

[МК51] Как в программу добавить проверку контрольной суммы (ассемблер)

28.11.2023, 15:27. Показов 642. Ответов 7
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Как в программу добывить проверку контрольной суммы.
Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
    org     0           
    jmp     start   
    org     23h 
    jmp     serial  
    org     30h 
start:      
    mov     tmod,#20h   ; Режим работы таймера
    mov     scon,#01010000b     ; Режим работы UART
    mov     th1,#0fdh   ; Скорость обмена
    mov     tl1,th1     
    mov     dptr,#0 ; Адрес принятых данных
    setb    tr1 ;Старт таймера - UART работает
    setb    es  ;Разрешить прерывания от uart
    setb    ea  
    clr     f0  ; Признак конца приема строки
wait_line:      ; Ожидание приема строки
    jnb     f0,$    ; Строка принята
    clr     f0  
    clr ren 
    mov    dptr,#0  
    setb        ti  ; Начать передачу
    jnb     f0,$    ; Строка передана
    clr     f0  
    setb      ren   
    mov    dptr,#0  
    jmp     wait_line   
serial:     
    jbc     ri,rec  
    clr     ti  
    movx    a,@dptr 
    cjne    a,#0dh,send ; Признак конца строки
    jmp      rte    
send:       
    mov     sbuf,a  
    jmp     d   
rec:        
    mov     a,sbuf  
    movx    @dptr,a 
te:     
    xrl     a,#0dh  ; Признак конца строки
    jnz     d   
rte:        
    setb    f0  
d:          inc     dptr    
    reti    
    end
Как я понимаю надо использовать вот эти биты,но как?
7 6 5 4 3 2 1 0
SM0 SM1 SM2 REN TB8 RB8 TI RI
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
28.11.2023, 15:27
Ответы с готовыми решениями:

Ассемблер на мк51
Всем здравствуйте, можете пожалуйста подсказать как можно реализовать функцию задержки между...

Загрузка и хранение файлов: имеет ли смысл добавить столбец контрольной суммы файла?
Загружаю файлы на сервер, для хранения файлов использую varbinary(max), имеет ли смысл добавить...

Создать программу на проверку логической микросхемы в ассемблер 8086
Исполнительным элементом в этом задании является логическая микросхема, тип которой указан в графе...

Ассемблер и МК51! Завал с курсовым проектом!!!!
Для курсового нужно написать на ассемблере программу которая выводит на МК51 определенное...

[МК51] программа генерации синусоидального сигнала переменной частоты (ассемблер)
Помогите написать программу генерации синусоидального сигнала переменной частоты. Программа на...

7
Модератор
1188 / 627 / 283
Регистрация: 10.11.2019
Сообщений: 1,322
28.11.2023, 16:03 2
Вывод байта через последовательный порт, или проклятые 3 команды.
Как ПРАВИЛЬНО работать с последовательным портом и как НЕ надо с ним работать.

1)
Неработающий вариант:

Assembler
1
2
3
4
5
6
7
8
C_OUT1:
;   Console character output routine.
;   Outputs character received in accumulator to console output device.
;
        JNB     TI,$            ;Wait until transmission completed.
        CLR     TI              ;Clear interrupt flag.
    MOV SBUF,A      ;Write out character.
    RET
Так сказать, "живой" (мёртвый) пример из ранней документации Intel.
На самом деле, флаг TI означает не "буфер передачи пустой",
а "закончена передача байта из буфера" и соответственно надо сначала записать в SBUF байт, а уж потом
дожидаться установки TI. Обходной вариант устранения ошибки: установить TI принудительно (setb TI) "где-то
в начале программы" в подпрограмме инициализации порта, чтобы добиться передачи первого байта.
А дальше "всё пойдет нормально". Весьма неудачный подход, в результате которого в работающей
программе порт "самым загадочным образом" отключается намертво. Эта ошибка как оказалось,
была допущена в ранних руководствах самой Intel (причем логика работы последовательного порта
была описана правильно). Потом Intel спохватились и "исправили" (?) ошибку, но было уже поздно -
ошибку растиражировали перепечатками и переводами. Я думаю, что это реально главная проблема
начинающих программистов на 51 контроллере, которые берут "описание" с таким советом.
(кстати, без единого намёка, что это перевод с документации Intel и без единой собственной мысли).

2)
Вариант 2, "усовершенствован Intel", но работает не всегда.
Код работает правильно, только если прерывание UART запрещено, либо
прерывание UART разрешено, но имеет самый низкий приоритет из разрешенных (как в 8051 по умолчанию):

Assembler
1
2
3
4
5
C_OUT2:
    MOV SBUF,A
        JNB     TI,$  
        CLR     TI    
    RET
Как, и этот код сбоит ? Да, и весьма необычно и редко, что усложняет обнаружение ошибки.
Предположим, мы используем _ввод_ байт через последовательный порт по прерываниям, причем программа
обработки выглядит как:

Assembler
1
2
3
4
5
6
7
8
serial_int:
    jnb RI, si0
    clr RI
        push ...
    .... ; код приёма байта
 
        pop  ...
si0:    reti
Т е кода сброса бита TI здесь нет. И действительно, как же тогда будет работать наша "передача без прерываний" ?
Предположим теперь, что у нас есть прерывание с более _низким_ приоритетом, чем прерывание последовательного
порта, причем оно разрешено. Например, в 8052 процессорах прерывание Таймера 2 имеет более низкий приоритет.
Или приоритет последовательного порта принудительно установлен в высокий.
Возникает такая ситуация. Мы обращаемся к C_OUT2, в результате чего контроллер довольно долго стоит в
цикле ожидания

Assembler
1
       JNB TI,$
Например, если скорость обмена 9600 Бод, то это будет около 1 миллисекунды.
В это время "совершенно случайно" приходит прерывание от таймера 2:

Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
timer2_int:push psw
    push acc
    push b
    push dpl
    push dph
    ...
    ...           ; *
 
 
    pop dph
        pop dpl
        pop b
        pop acc
        pop psw
        reti
* - ... и где-то здесь "совершенно случайно" UART заканчивает передачу байта и устанавливает TI.
Поскольку прерывание UART разрешено, то оно тут же выполняется. Но т к оно не сбрасывает TI, то происходит
такая вещь. Как только идет reti из подпрограммы прерывания UART в подпрограмму timer2_int, то выполняется ровно 1
команда из подпрограммы timer2_int, после чего опять возникает serial_int и т д. Т е в результате процесс
выполнения timer2_int затягивается в десятки раз, потому что каждая команда timer2_int (начиная со
случайного адреса) будет сопровождаться вызовом и возвратом serial_int До того,
как проклятый код наконец не достигнет

Assembler
1
2
  JNB     TI,$  
  CLR     TI
после чего всё придёт в норму. Самое интересное, что никаких ошибок в математике тут не возникает,
но если прерывание Таймера 2 управляет аппаратурой, то "что-то начинает дёргаться". Причем и последовательный
порт вполне естественно "сбоит".

3) Вариант 3, неплохой (?)

Работает правильно, только если прерывание UART разрешено:

Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
C_OUT3:
    MOV SBUF,A
        JNB     myTI,$  
        CLR     myTI    
    RET
 
 
serial_int:
    jnb RI, si0
    clr RI
        push ...
    .... ; код приёма байта
 
        pop  ...
si0:    JNB TI, si1 ; в предположении, что байт передаётся как в C_OUT3
        clr  TI     ; сбросить TI, чтобы он не вызвал повторного обращения к прерыванию
        setb myTI   ; установить собственный флаг myTI, чтобы получить информацию о конце передачи байта
si1:    reti
То есть мы сбрасываем флаг прерывания TI и одновременно устанавливаем наш собственный "самый обычный"
флаг.

Мораль: оказывается, работа UART по прерываниям и без - это принципиально разные режимы.
Программа обработки прерываний должна _всегда_ явно сбрасывать биты RI и TI, если они установлены.
Т е если Вы вдруг задумали перевести чтение байт из UART "с опроса бита состояния на работу по прерываниям",
или наоборот, то нужно соответственно поменять и программу записи байт в порт. Это кажется настолько
очевидным ... настолько, что об этом никто не знает ?
0
0 / 0 / 0
Регистрация: 04.05.2023
Сообщений: 8
28.11.2023, 16:49  [ТС] 3
А если сделать так: сумируем передаваемые числа, их инвертируем, а затем сумируем с суммой полученных данных и получаем ноль. Это значит что данные переданы верно.
Вопрос? А как записать это в эту программу. Просто непонятно.
0
Модератор
1188 / 627 / 283
Регистрация: 10.11.2019
Сообщений: 1,322
28.11.2023, 17:19 4
Ваша первая задача - исправить приём и передачу символов и программу обработки прерывания.
Сейчас программа в целом - не рабочая.
Допустим, мы вычислили контрольную сумму строки и поместили ее в байт с адресом 30h
Тогда нам после выдачи строки в порт надо добавить две цифры контрольной суммы - примерно так:

Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
; тестировалась в Mide-51
 
csum    equ 30h ; байт контрольной суммы
ctext1  equ 31h ; цифры контрольной суммы
ctext2  equ 32h
    org 0
start:  mov csum,#9Bh ; предположим, это наша контр сумма
    mov a,csum
    call convtext ; преобразуем a в hex цифры
    call print    ; выводим цифры в порт
    jmp $
convtext:mov b,#10h ; делим a на 16 - получаем 2 цифры
    div ab
    call digit   ; преобр цифру в сиввол
    mov ctext1,a ; запомнить
    mov a,b       
    call digit   ; преобр цифру в сиввол
    mov ctext2,a ; запомнить
    ret
print:  ret ; здессь должен быть код передачи цифр в порт
digit:  mov dptr,#dig
    movc a,@a+dptr
    ret
dig:    db "0123456789ABCDEF"
    end
Добавлено через 2 минуты
Напишите также, на чём Вы пишите программу и как отлаживаете.
0
0 / 0 / 0
Регистрация: 04.05.2023
Сообщений: 8
28.11.2023, 21:15  [ТС] 5
Пишу программу на ассемблере для микроконтроллера мк51 (8051). ОТЛАЖИВАЮ В KeiluVision
0
6770 / 2739 / 384
Регистрация: 17.02.2013
Сообщений: 4,048
29.11.2023, 09:56 6
Цитата Сообщение от qbfan Посмотреть сообщение
Обходной вариант устранения ошибки: установить TI принудительно (setb TI) "где-то
в начале программы" в подпрограмме инициализации порта, чтобы добиться передачи первого байта.
А дальше "всё пойдет нормально". Весьма неудачный подход, в результате которого в работающей
программе порт "самым загадочным образом" отключается намертво.
Непонятно каков механизм того, что порт отключается намертво в этом случае (предполагается, что прерывания запрещены).
0
Модератор
1188 / 627 / 283
Регистрация: 10.11.2019
Сообщений: 1,322
29.11.2023, 15:26 7
Цитата Сообщение от Ethereal Посмотреть сообщение
предполагается, что прерывания запрещены
На самом деле, как раз желательно сделать чтение по прерываниям.
Т к при этом меньше возможности потерять байты при приёме.
Я занимался разработкой чековых принтеров, и там вполне естественно требовалось
обеспечить приём данных по прерываниям в то время, пока принтер печатает строку.
Но при этом и возникали те проблемы, о которых я писал выше.
0
Модератор
1188 / 627 / 283
Регистрация: 10.11.2019
Сообщений: 1,322
29.11.2023, 19:00 8
Вот пример программы, которая работает с com портом
и вычисляет контрольную сумму введённой строки
(см аттач с проектом)

csum.uv2 - запускаемый проект Keil (Keil 7.03)

В Keil:
Компилировать программу
Запустить отладчик (Start-Stop Debug Session)
Открыть окно View/Serial Window #1
Запустить программу (F5)
При этом программа отладчика работает как терминал, т е можно вводить
с клавиатуры строку и наблюдать результат.
Точно так же программа должна работать на реальной схеме МК,
подключённой к компьютеру через программу - терминал.
(Но не забудьте, что программа использует память xdata)

Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
; Ввод текста через посл порт в xdata и вывод его с контрольной суммой
 
REG0 equ 0 ; адрес регистра
REG2 equ 2 ; адрес регистра
myTI bit 0 ; флаг Вывод символа завершён
txtready bit 1 ; флаг Строка готова
txtlen equ 16 ; длина буфера ввода
outbuf equ 16 ; адрес буфера вывода
; (фдрес буфера ввода=0)
checksum equ 30h ; байт контрольной суммы
    org     0           
    jmp     start   
    org     23h 
    jmp     serial  
    org     30h 
start:      
    mov     tmod,#20h ; инит послед порт
    mov     scon,#01010000b
    mov     th1,#0fdh
    mov     tl1,th1     
    mov     dptr,#0
    setb    tr1
    setb    es
    setb txtready ; флаг=1 (ввод данных в порт запрещён)
    setb    ea
main:mov dptr,#mess1
    call cprint
    call xinput ; ввести строку данных
    mov dptr,#mess2
    call cprint
    mov R1,#outbuf ; вывести строку данных
    call xprint
    mov R1,#outbuf
    call findcs ; найти контр сумму
    mov a,#"["
    call pchar
    call printcs ; напечатать контр сумму
    mov a,#"]"
    call pchar
    mov dptr,#mess3
    call cprint
    jmp main
 
copyinput:mov P2,#0 ; копировать буфер ввода в строку вывода
    mov R0,#0
    mov R1,#outbuf
    mov R2,#txtlen
copy1:  movx A,@R0
    movx @R1,A
    inc R0
    inc R1
    djnz R2,copy1
    ret
 
clrinput:mov P2,#0 ; очистить буфер ввода
    mov R0,#0
    mov R2,#txtlen
    clr A
clr1:   movx @R0,A
    inc R0
    djnz R2,clr1
    ret
    
xinput: call clrinput ; ввод строки
    mov P2,#0
       mov R1,#0 ; R1=R0=начало буфера
       mov R0,#0
       clr txtready ; разрешить ввод строки
xin0:  jb txtready,xin2 ; если строка готова, то выход
       mov A,R1 ; если есть ненапечатанные символы в буфере, то напечатать
       cjne A,REG0,xin1
       jmp xin0
xin1:  movx A,@R1
       call pchar
       inc R1
       jmp xin0
xin2:   call copyinput
    ret
 
findcs: clr A ; подсчёт контр суммы
    mov R2,a
findcs0:movx a,@R1
    inc R1
    jnz findcs1
    mov checksum,R2
    ret
findcs1:xrl REG2,A ; здесь надо вставить нормальный алгоритм контр суммы
    jmp findcs0
 
printcs:mov A,checksum ; печать контр суммы в 16 ричном виде
    mov b,#16
    div ab
    call digit
    call pchar
    mov a,b       
    call digit
    call pchar
    ret
digit:  mov dptr,#dig
    movc a,@a+dptr
    ret
dig:    db "0123456789ABCDEF"
 
 
xprint: movx a,@R1 ; печать строки из xdata (точнее - pdata)
    inc R1
    jnz xpri1
    ret
xpri1:  call pchar
    jmp xprint
 
cprint: clr a ; печать строки из RON
    movc a,@a+dptr
    inc dptr
    jnz cpri1
    ret
cpri1:  call pchar
    jmp cprint
 
pchar:  mov sbuf,a ; вывод A в послед порт
    jnb myti,$
    clr myti
    ret
 
; обработка послед прерываний
; использует R0, заполняет xdata от адреса 0 до txtlen
serial: jnb ri,s1
    clr ri
    jb txtready,s1
    cjne R0,#(txtlen-2),s0
        setb txtready
    jmp s1
s0: push acc
        mov a,sbuf
    movx @R0,A
    inc R0
    cjne A,#13,s3
    dec R0
    clr A
    movx @R0,A
    setb txtready
s3: pop acc
s1: jnb ti,s2
    clr ti
    setb myTi
s2: reti
mess1: db "Input a string:",13,10,0
mess2: db 13,10,"Your input is:",13,10,0
mess3: db 13,10,0
    end
Вложения
Тип файла: zip csum51.zip (15.1 Кб, 4 просмотров)
0
29.11.2023, 19:00
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
29.11.2023, 19:00
Помогаю со студенческими работами здесь

[МК51] Сложение двух 4-байтных чисел в BCD-коде (ассемблер)
4. Подпрограмма сложения двух 4-байтных чисел в BCD-коде. Адрес первого слагаемого - в регистре...

МК51 (аналог intel 8051): как добавить бит четности?
Здравствуйте! В массиве 20Н-27Н РПД микроконтроллера МК51 подготовлены для передачи семиразрядные...

Добавить проверку в программу на простые числа, чтобы программа работала как прежде без ошибок
#define DATA_1_PIN 10 // пин данных для первого регистра #define DATA_2_PIN 13 // пин данных для...

МК51 Программа формирования ШИМ сигнала с пилообразным изменением коэффициента заполнения (Ассемблер)
Помогите написать Программу на ассемблере для микроконтроллера МК51 формирования ШИМ сигнала с...

Написать программу, которая должна проверять правильность контрольной суммы и выводить отчёт
Текст задачи: "По каналу связи передаётся последовательность положительных целых чисел, все числа...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
8
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru