forked from unfrozen/stm8_libs
-
Notifications
You must be signed in to change notification settings - Fork 2
/
lib_adc.c
140 lines (129 loc) · 2.74 KB
/
lib_adc.c
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
/*
* File name: lib_adc.c
* Date first: 09/14/2018
* Date last: 09/15/2018
*
* Description: Library for using STM8S ADC.
*
* Author: Richard Hodges
*
* Copyright (C) 2018 Richard Hodges. All rights reserved.
* Permission is hereby granted for any use.
*
******************************************************************************
*
*/
#include "stm8s_header.h"
#include "lib_adc.h"
#ifdef STM8103
#define CR1_VAL 0x21 /* 16mhz / 4 = 4mhz ADC */
#endif
#ifdef STM8105
#define CR1_VAL 0x01 /* 8mhz / 2 = 4mhz ADC */
#endif
/******************************************************************************
*
* Initialize
* in: bits for ADC channel(s) to use
* (Note that this may be called from multiple sub-systems)
*/
void adc_init(char chans)
{
#ifdef ORIG_C
ADC_TDRL |= chans & ADC_MASK; /* disable schmitt triggers for analog */
if (chans & ADC_CH12)
ADC_TDRH |= 0x10;
ADC_CR2 = 0x08; /* result is right aligned */
ADC_CR1 = CR1_VAL; /* enable ADC */
#else
chans;
__asm
ld a, (3, sp)
and a, #ADC_MASK
ldw x, #_ADC_TDRL
or a, (x)
ld (x), a
ld a, (3, sp)
and a, #ADC_CH12
jreq 00001$
bset _ADC_TDRH, #4
00001$:
mov _ADC_CR2, #0x08
mov _ADC_CR1, #CR1_VAL
__endasm;
#endif
}
/******************************************************************************
*
* Get average of 4 A/D samples
* in: ADC channel (0 to 12)
* out: 10-bit A/D average value, -1 if timeout
*/
short adc_avg(char chan)
{
#ifdef ORIG_C
short avg, val;
char i;
avg = 2;
for (i = 0; i < 4; i++) {
val = adc_val(chan);
if (val < 0)
return -1;
avg += val;
}
return avg >> 2;
#else
#pragma disable_warning 59
chan;
__asm
ldw x, #2
pushw x
push #4
00001$:
ld a, (6, sp)
push a
call _adc_val
pop a
tnzw x
jrmi 000090$
addw x, (2, sp)
ldw (2, sp), x
dec (1, sp)
jrne 00001$
srlw x
srlw x
00090$:
add sp, #3
__endasm;
#endif
}
/******************************************************************************
*
* Get current raw A/D value
* in: ADC channel (0 to 12)
* out: 10-bit A/D conversion value, -1 if timeout
*/
#pragma disable_warning 59
short adc_val(char chan)
{
chan;
__asm
bres _ADC_CSR, #7 ; clear end of conversion flag
ld a, (3, sp)
ld _ADC_CSR, a ; set A/D channel
bset _ADC_CR1, #0 ; start conversion
ld a, #100 ; conversion is 3.5 uS, 56 cycles @ 16mhz
00001$:
btjt _ADC_CSR, #7, 00090$ ; (2)
dec a ; (1)
jrne 00001$ ; (2) = 5 per loop, should be done < 12
clrw x
decw x
ret
00090$:
ld a, _ADC_DRL ; (24.11.8) read DRL first with right-justify
ld xl, a
ld a, _ADC_DRH
ld xh, a
__endasm;
}