использование глобального значения в FreeRTOS внутри таймера ISR

С помощью:

  • Arduino Mega 2560
  • Arduino IDE
  • Timer2

Код:

#include "FreeRTOS_AVR.h"#include "basic_io_avr.h"
/***
* HITEC servo ranges from 0.9 to 2.4 ms
* values in usec
***/

const int firstPulse = 0.7 * 1000;
const int centerPulse = 1.5 * 1000;
const int lastPulse = 2.4 * 1000;
const int cycleLength = 20 * 1000;
const int degree = (lastPulse - firstPulse) / 180 * 1.0; //9.44
const int SERVO_PIN = 29;
const int ULTRASOON_PIN = 43;

void servoTask(void* p);
void ultrasoonTask(void* p);
void receiveTask(void* p);

QueueHandle_t xQueueDistance, xQueueDegrees;

void setup() {
// put your setup code here, to run once:
cli();
USART_init();
Timer2_init();
Timer3_init();
sei();
pinMode(SERVO_PIN, OUTPUT);

xQueueDistance = xQueueCreate(1, sizeof(uint8_t));
xQueueDegrees = xQueueCreate(1, sizeof(int));

xTaskCreate(servoTask, "Servo task", 200, NULL, 1, NULL);
xTaskCreate(ultrasoonTask, "Ultrasoon task", 200, NULL, 1, NULL);
xTaskCreate(receiveTask, "Receive task", 200, NULL, 1, NULL);
vTaskStartScheduler();

while(1) {writeString("DEAD LOOP\n");};
}

volatile int pulse=0;
ISR (TIMER2_COMPA_vect) {
static int x=0;

x++;
if(x%2) {
//vPrintStringAndNumber("ServoPos= ", pulse);
//moveServo(pulse);
}
}

ISR( TIMER3_COMPA_vect){}

void ultrasoonTask(void* p) {
uint8_t ultrasoonValue;
portBASE_TYPE xStatus;

while(1) {
ultrasoonValue = ping();
//vPrintStringAndNumber("Ping= ", ultrasoonValue);
xQueueSendToBack(xQueueDistance, &ultrasoonValue, 0);
vTaskDelay(500 / portTICK_PERIOD_MS);
}
}

void servoTask(void *p) {
uint8_t inValue;
int m_degrees;
portBASE_TYPE xStatus;

while(1) {
xStatus = xQueueReceive(xQueueDistance, &inValue, 0);
if(xStatus == pdPASS) {
//vPrintStringAndNumber("ServoRead= ", inValue);
m_degrees = changeServoPosition((int)inValue);
//vPrintStringAndNumber("ServoPos= ", m_degrees);
xQueueSendToBack(xQueueDegrees, &m_degrees, 0);
}
vTaskDelay(500 / portTICK_PERIOD_MS);
}
}

void receiveTask(void* p) {
int m_degrees;
portBASE_TYPE xStatus;

while(1) {
xStatus = xQueueReceive(xQueueDegrees, &m_degrees, 0);
if(xStatus == pdPASS) {
//vPrintStringAndNumber("ServoPos= ", m_degrees);
pulse = m_degrees;
//vPrintStringAndNumber("ServoPos= ", pulse);
}
vTaskDelay(500 / portTICK_PERIOD_MS);
}
}

long ping() {
pinMode(ULTRASOON_PIN, OUTPUT); // Switch signalpin to output
digitalWrite(ULTRASOON_PIN, LOW); // Send low pulse
delayMicroseconds(2); // Wait for 2 microseconds
digitalWrite(ULTRASOON_PIN, HIGH); // Send high pulse
delayMicroseconds(5); // Wait for 5 microseconds
digitalWrite(ULTRASOON_PIN, LOW); // Holdoff

pinMode(ULTRASOON_PIN, INPUT); // Switch signalpin to input
digitalWrite(ULTRASOON_PIN, HIGH); // Turn on pullup resistor

long temp = pulseIn(ULTRASOON_PIN, HIGH); //Listen for echo

//convert to CM: sound speed is 340 m/s. 29microseconds/cm.
//                 ping signal travels out and back, take half distance travelled.
return temp / 29 / 2;
}

void moveServo(int p) {
digitalWrite(SERVO_PIN, HIGH);
delayMicroseconds(p);
digitalWrite(SERVO_PIN, LOW);
delayMicroseconds(cycleLength - p);
}

int changeServoPosition(int in) {
int p = in * degree + firstPulse;
if(p < firstPulse) {
p = firstPulse;
} else if(p > lastPulse) {
p = lastPulse;
}
return p;
}

void Timer2_init() {
TCCR2A = 0;
TCCR2B = 0;
//  CTC Mode
TCCR2B |= (1<<WGM22);
//
//  Prescaler mode: 1024
TCCR2B |= (1<<CS22) | (1<<CS20);

TIMSK2 = (1<<OCIE2A); //interrupt enable
TCNT2 = 0;
OCR2A = 156;
}

/**
*  Timer3 is 16 bits, max tellen tot 2^16= 65535
*  OCR3A = FCPU / prescaler / frequentie
*  FCPU = 16000000, Prescaler = 1024, FCPU/Prescaler = 15625
*  Frequentie = 1/(time in seconds), 20ms = 0.02s, 1/s = 50Hz
*  OCR3A = 312.5
**/

void Timer3_init() {
TCCR3A = 0;
TCCR3B = 0;

//  CTC Mode
TCCR3B |= (1<<WGM32);
//  Prescaler mode: 1024
TCCR3B |= (1<<CS32) | (1<<CS30);

TIMSK3 = (1<<OCIE3A); //interrupt enable
TCNT3 = 0;
OCR3A = 313;
}

void USART_init() {
/* Set baud rate */
UBRR0H = 0;//UBRR0H = (unsigned char)(ubrr>>8);
UBRR0L = 16000000/16/9600-1; //FCPU en BAUD. UBRR0L = (unsigned char)ubrr;
UCSR0A = 0;
/* Enable receiver and transmitter */
UCSR0B = (1<<RXEN0)|(1<<TXEN0);
/* Set frame format: 8data, 2stop bit */
UCSR0C = (1<<USBS0)|(3<<UCSZ00);  // URSEL: Register select, om op UCSRC te schrijven
// USBS:  op 2stop bit zetten
// UCSZ0: 3 erop schuiven, hierdoor UCSZ0 en UCSZ1 op 1 geset. 8 bit
}

void writeChar(char data){
/* Wait for empty transmit buffer */
while ( !( UCSR0A & (1<<UDRE0)) );    // UDRE is een flag die wacht totdat data in de buffer gezet mag worden.
/* Put data into buffer, sends the data */
UDR0 = (uint8_t)data;
}

void writeString(char* str){
while(*str)
writeChar(*str++);
}

void writeInteger(int16_t number, uint8_t base){
char nmb[3];
itoa(number, nmb, base);
writeString(nmb);
}

char readChar(){
/* Wait for data to be received */
while ( !(UCSR0A & (1<<RXC0)) );      // RXC is een flag die wacht totdat er data bij de buffer van de ontvanger is.
/* Get and return received data from buffer */
return (char)UDR0;
}

void loop(){
}

Проблема:

volatile int pulse это глобальная переменная, которую я хочу использовать в ISR Timer2.
С receiveTaskЯ получаю значение из очереди и устанавливаю его в качестве значения импульса.

Но каждый раз значение пульса равно 0.

0

Решение

То, как вы используете xQueueReceive () Функция выглядит корректно, поэтому при условии, что тест if (xStatus == pdPASS) действительно проходит, я предполагаю, что проблема на самом деле в том, где вы отправляете значение в очередь, а не в том месте, где вы его получаете. Вы не показываете этот код, хотя. Вы уверены, что действительно пишете в очередь, и что значение, записываемое в очередь, не всегда равно 0?

0

Другие решения


По вопросам рекламы [email protected]