-
Notifications
You must be signed in to change notification settings - Fork 0
/
sensors.c
142 lines (118 loc) · 3.19 KB
/
sensors.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
141
142
/*
* sensors.c
*
* Created on: 01.03.2015
* Author: a_pol@hotbox.ru
*/
#include "ch.h"
#include "hal.h"
#include "main.h"
#include "sensors.h"
#include "modbus_slave.h"
#define SENSORS_TIMEOUT_MS 2 // задержка опроса датчиков, mS
#define ADC_TIMEOUT_US 100 // задержка опроса датчиков, uS
static volatile adc_error_t adcerror; // флаг преобразования ADC
uint16_t samples[SENSORSALL]; // описание датчиков
static binary_semaphore_t adcsem; // семафор доступа к ADC
static binary_semaphore_t adc_cbsem; // семафор чтения ADC
volatile uint16_t adc_tempint;
volatile uint16_t adc_vrefint;
#define ADCRead_PRIO (NORMALPRIO+1)
static THD_WORKING_AREA(waADCReadThread, 256);
void adccallback(ADCDriver *adcp, adcsample_t *buffer, size_t n);
void adcerrcallback(ADCDriver *adcp, adcerror_t err);
/*
* ADC conversion group.
*/
#define ADC_SAMPLE ADC_SAMPLE_239P5
static const ADCConversionGroup adcgrpcfg = {
FALSE, //circular
SENSORSALL, //number of channels
adccallback, //adc callback function
adcerrcallback, //error callback function
/* HW dependent part.*/
0, //cr1
ADC_CR2_TSVREFE, //cr2
//SMPR1 register
ADC_SMPR1_SMP_VREF(ADC_SAMPLE) |
ADC_SMPR1_SMP_SENSOR(ADC_SAMPLE) |
0,
//SMPR2 register
0,
//SQR1 register
ADC_SQR1_NUM_CH(SENSORSALL),
//SQR2 register
0,
//SQR3 register
ADC_SQR3_SQ2_N(ADC_CHANNEL_VREFINT) |
ADC_SQR3_SQ1_N(ADC_CHANNEL_SENSOR) |
0,
};
/*
* ADC end conversion callback
*/
void adccallback(ADCDriver *adcp, adcsample_t *buffer, size_t n) {
(void) buffer;
(void) n;
if (adcp->state == ADC_COMPLETE){
chSysLockFromISR();
chBSemSignalI(&adc_cbsem);
chSysUnlockFromISR();
}
}
void adcerrcallback(ADCDriver *adcp, adcerror_t err) {
(void)adcp;
(void)err;
if (adcp->state == ADC_ERROR){
adcerror = ADC_CONV_ERROR;
}
chSysLockFromISR();
chBSemSignalI(&adc_cbsem);
chSysUnlockFromISR();
}
/*
* ADC read process
*/
static thread_t *ADCReadThread_p;
static THD_FUNCTION(ADCReadThread, arg) {
(void)arg;
chRegSetThreadName("ADCRead");
chBSemObjectInit(&adc_cbsem,TRUE);
while (TRUE) {
msg_t req;
thread_t *tp;
tp = chMsgWait();
req = chMsgGet(tp);
chMsgRelease(tp, (msg_t) req);
adcerror = ADC_NO_ERROR;
chBSemReset(&adc_cbsem,TRUE);
adcStartConversion(&ADCD1, &adcgrpcfg, samples, 1);
if (chBSemWaitTimeout(&adc_cbsem, TIME_US2I(ADC_TIMEOUT_US)) == MSG_TIMEOUT) {
adcerror = ADC_TIMEOUT;
}
if (adcerror == ADC_NO_ERROR) {
adc_tempint = samples[TEMPINT];
adc_vrefint = samples[VREFINT];
}
chBSemSignal(&adcsem);
}
}
/*
* Initializes the ADC driver 1.
*/
void sensors_init(void){
adcStart(&ADCD1, NULL);
chBSemObjectInit(&adcsem,FALSE);
ADCReadThread_p = chThdCreateStatic(waADCReadThread, sizeof(waADCReadThread), ADCRead_PRIO, ADCReadThread, NULL);
}
adc_error_t sensors_read(void) {
msg_t *adc_read_p = 0;
chBSemWait(&adcsem); /* to be sure */
chMsgSend(ADCReadThread_p, (msg_t) adc_read_p);
/* wait for reply */
if(chBSemWaitTimeout(&adcsem, TIME_MS2I(SENSORS_TIMEOUT_MS)) == MSG_TIMEOUT) {
return ADC_TIMEOUT;
}
chBSemReset(&adcsem, FALSE);
return adcerror;
}