-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathMCP320x.asm
246 lines (232 loc) · 8.37 KB
/
MCP320x.asm
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
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
;------------------------------------------------------------------------------
; Подпрограммы для работы с АЦП MCP3204, MCP3208
; 12-битный АЦП
; SPI интерфейс
;
; Не доработано для MCP3208 (TODO сделать проверку по числу каналов от 4 до 7)
;
; (C) 2017-2020 Vitaliy Zinoviev
; https://github.com/nf-zvv/IVC_Tracer_v2
;
; History
; =======
; 27.05.2019 добавлен 3 канал АЦП (теперь задействованы все 4 канала АЦП)
;------------------------------------------------------------------------------
#ifndef _MCP320X_ASM_
#define _MCP320X_ASM_
.ifndef __zero_reg__
.def __zero_reg__ = r2
.endif
;-------------------------------------------
; Подключение MCP3204 к МК ATmega16 |
;-------------------------------------------|
; PB7 ( 8 выв.) (SCK) - CLK (11 выв.)
; PB6 ( 7 выв.) (MISO) - Dout(10 выв.)
; PB5 ( 6 выв.) (MOSI) - Din (9 выв.)
; PD6 (20 выв.) (PD6) - CS (8 выв.)
;-------------------------------------------
.equ ADC_CS_DDR = DDRD
.equ ADC_CS_PORT = PORTD
.equ ADC_CS = PD5
.dseg
ADC_CH0: .byte 2
ADC_CH1: .byte 2
ADC_CH2: .byte 2
ADC_CH3: .byte 2
ADC_DATA: .byte 2
ADC_CH0_SUM: .byte 2
ADC_CH1_SUM: .byte 2
ADC_CH2_SUM: .byte 2
ADC_CH3_SUM: .byte 2
SUM_COUNTER: .byte 1
.cseg
;------------------------------------------------------------------------------
; Инициализация АЦП MCP3204
;
; Вызовы: -
; Используются: -
; Вход: -
; Выход: -
;------------------------------------------------------------------------------
ADC_INIT:
; настройка линий ввода/вывода
sbi ADC_CS_DDR,ADC_CS ; ADC CS output
sbi ADC_CS_PORT,ADC_CS ; CS=1
ret
;------------------------------------------------------------------------------
; Получение и усреднение результатов всех кангалов АЦП
; усреднение по 16 выборкам
;
; Вызовы: ADC_GET_SNGL[r16,r17], DIV_16[r16,r17]
; Используются: r14,r15,r16,r17
; Вход: -
; Выход: ADC_CH0, ADC_CH1, ADC_CH2, ADC_CH3
;------------------------------------------------------------------------------
ADC_RUN:
sts ADC_CH0_SUM+0,__zero_reg__ ; Очищаются байты суммирования
sts ADC_CH0_SUM+1,__zero_reg__ ; Чтобы новый результат был с нуля
sts ADC_CH1_SUM+0,__zero_reg__ ; Очищаются байты суммирования
sts ADC_CH1_SUM+1,__zero_reg__ ; Чтобы новый результат был с нуля
sts ADC_CH2_SUM+0,__zero_reg__ ; Очищаются байты суммирования
sts ADC_CH2_SUM+1,__zero_reg__ ; Чтобы новый результат был с нуля
sts ADC_CH3_SUM+0,__zero_reg__ ; Очищаются байты суммирования
sts ADC_CH3_SUM+1,__zero_reg__ ; Чтобы новый результат был с нуля
ldi r16,16 ; Заполняется счетчик новым числом
sts SUM_COUNTER,r16
ADC_RUN_LOOP:
; Работаем с нулевым каналом АЦП
ldi r16,0
rcall ADC_GET_SNGL ; получаем значение
; загружаем числа
lds r15,ADC_CH0_SUM+1 ; старший байт суммы
lds r14,ADC_CH0_SUM+0 ; младший байт суммы
lds r17,ADC_DATA+1 ; старший байт
lds r16,ADC_DATA+0 ; младший байт
; добавляем к сумме
add r14,r16 ; Младший байт суммируется без переноса
adc r15,r17 ; Старший байт суммируется с учетом переноса
sts ADC_CH0_SUM+1,r15
sts ADC_CH0_SUM+0,r14
; Работаем с первым каналом АЦП
ldi r16,1
rcall ADC_GET_SNGL ; получаем значение
; загружаем числа
lds r15,ADC_CH1_SUM+1 ; старший байт суммы
lds r14,ADC_CH1_SUM+0 ; младший байт суммы
lds r17,ADC_DATA+1 ; старший байт
lds r16,ADC_DATA+0 ; младший байт
; добавляем к сумме
add r14,r16 ; Младший байт суммируется без переноса
adc r15,r17 ; Старший байт суммируется с учетом переноса
sts ADC_CH1_SUM+1,r15
sts ADC_CH1_SUM+0,r14
; Работаем со вторым каналом АЦП
ldi r16,2
rcall ADC_GET_SNGL ; получаем значение
; загружаем числа
lds r15,ADC_CH2_SUM+1 ; старший байт суммы
lds r14,ADC_CH2_SUM+0 ; младший байт суммы
lds r17,ADC_DATA+1 ; старший байт
lds r16,ADC_DATA+0 ; младший байт
; добавляем к сумме
add r14,r16 ; Младший байт суммируется без переноса
adc r15,r17 ; Старший байт суммируется с учетом переноса
sts ADC_CH2_SUM+1,r15
sts ADC_CH2_SUM+0,r14
; Работаем с третьим каналом АЦП
ldi r16,3
rcall ADC_GET_SNGL ; получаем значение
; загружаем числа
lds r15,ADC_CH3_SUM+1 ; старший байт суммы
lds r14,ADC_CH3_SUM+0 ; младший байт суммы
lds r17,ADC_DATA+1 ; старший байт
lds r16,ADC_DATA+0 ; младший байт
; добавляем к сумме
add r14,r16 ; Младший байт суммируется без переноса
adc r15,r17 ; Старший байт суммируется с учетом переноса
sts ADC_CH3_SUM+1,r15
sts ADC_CH3_SUM+0,r14
; Проверяем условие
lds r16,SUM_COUNTER
dec r16
sts SUM_COUNTER,r16
breq ADC_RUN_CONTINUE
rjmp ADC_RUN_LOOP
ADC_RUN_CONTINUE:
; Усредняем значения нулевого канала
lds r17,ADC_CH0_SUM+1 ; старший байт суммы
lds r16,ADC_CH0_SUM+0 ; младший байт суммы
rcall DIV_16 ; Деление 16-разрядного числа (r17:r16) на 16
sts ADC_CH0+1,r17 ; результат деления (старший байт)
sts ADC_CH0+0,r16 ; результат деления (младший байт)
; Усредняем значения первого канала
lds r17,ADC_CH1_SUM+1 ; старший байт суммы
lds r16,ADC_CH1_SUM+0 ; младший байт суммы
rcall DIV_16 ; Деление 16-разрядного числа (r17:r16) на 16
sts ADC_CH1+1,r17 ; результат деления (старший байт)
sts ADC_CH1+0,r16 ; результат деления (младший байт)
; Усредняем значения второго канала
lds r17,ADC_CH2_SUM+1 ; старший байт суммы
lds r16,ADC_CH2_SUM+0 ; младший байт суммы
rcall DIV_16 ; Деление 16-разрядного числа (r17:r16) на 16
sts ADC_CH2+1,r17 ; результат деления (старший байт)
sts ADC_CH2+0,r16 ; результат деления (младший байт)
; Усредняем значения третьего канала
lds r17,ADC_CH3_SUM+1 ; старший байт суммы
lds r16,ADC_CH3_SUM+0 ; младший байт суммы
rcall DIV_16 ; Деление 16-разрядного числа (r17:r16) на 16
sts ADC_CH3+1,r17 ; результат деления (старший байт)
sts ADC_CH3+0,r16 ; результат деления (младший байт)
ret
;------------------------------------------------------------------------------
; Подпрограмма деления 16-разрядного числа на 16
;------------------------------------------------------------------------------
DIV_16:
LSR r17 ; Сдвигается значение вправо, сначала старший
ROR r16 ; потом младший. Через флаг переноса.
LSR r17 ; Всего надо сделать 4 сдвига 2^4=16
ROR r16 ; Что будет эквивалентно делению на 16
LSR r17
ROR r16
LSR r17 ; Теперь в R17:R16 готовое 12 байтное
ROR r16 ; усредненное число
RET
;------------------------------------------------------------------------------
; Чтение из АЦП MCP3204
; Одиночный канал
;
; Вызовы: SPI_RW
; Используются: r16,r17
; Вход: r16 - номер канала (0...3)
; Выход: ADC_DATA
;------------------------------------------------------------------------------
ADC_GET_SNGL:
mov r17,r16
swap r17 ; перемещаем номер канала
lsl r17 ; на нужную
lsl r17 ; позицию
cbi ADC_CS_PORT,ADC_CS ; активация MCP3204
ldi r16,0b00000110 ; #2 - Start bit; #1 - single mode
rcall SPI_RW
mov r16,r17 ; #7,#6 - input channel
rcall SPI_RW ; отправляем и получаем байт
andi r16,0b00001111 ; очищаем ненужные биты
sts ADC_DATA+1,r16 ; сохраняем старший байт
clr r16
rcall SPI_RW ; отправляем и получаем байт
sts ADC_DATA+0,r16 ; сохраняем младший байт
sbi ADC_CS_PORT,ADC_CS ; деактивация MCP3204
ret
;------------------------------------------------------------------------------
; Чтение из АЦП MCP3204
; Дифференциальный режим
;
; Канал 0: CH0+, CH1-
; Канал 3: CH2+, CH3-
;
; Вызовы: SPI_RW
; Используются: r16,r17
; Вход: r16 - номер канала (0 или 3)
; Выход: ADC_DATA
;------------------------------------------------------------------------------
ADC_GET_DIFF:
mov r17,r16
swap r17 ; перемещаем номер канала
lsl r17 ; на нужную
lsl r17 ; позицию
cbi ADC_CS_PORT,ADC_CS ; активация MCP3204
ldi r16,0b00000100 ; #2 - Start bit; #1 - single mode
rcall SPI_RW
mov r16,r17 ; #7,#6 - input channel
rcall SPI_RW ; отправляем и получаем байт
andi r16,0b00001111 ; очищаем ненужные биты
sts ADC_DATA+0,r16 ; сохраняем старший байт
clr r16
rcall SPI_RW ; отправляем и получаем байт
sts ADC_DATA+1,r16 ; сохраняем младший байт
sbi ADC_CS_PORT,ADC_CS ; деактивация MCP3204
ret
#endif /* _MCP320X_ASM_ */
;------------------------------------------------------------------------------
; End of file
;------------------------------------------------------------------------------