-         

Ergebnis 1 bis 7 von 7

Thema: MPLAB 8, ICD2, C30 ... Multitasking?

  1. #1
    Benutzer Stammmitglied
    Registriert seit
    24.10.2007
    Ort
    Loughborough
    Alter
    34
    Beiträge
    53

    MPLAB 8, ICD2, C30 ... Multitasking?

    Anzeige

    Hallo Leute,

    ich habe die Tage mal angefangen den dsPIC30F zu proggen. Geht auch ganz gut, bis ich versucht habe multitasking zu implementieren.

    Ich habe vorher die typischen Lego-Controller(RCX) programmiert. Ich glaube die waren von Hitachi. Dort konnte man schoen einfach ueber execi(...) usw. mehrere Tasks starten, die "parallel" liefen (ich weiss, dass das nicht wirklich geht, aber ich denke, ihr wisst, was ich meine).

    Die Frage ist nun: geht das auch beim dsPIC30F? Wenn ja, hat das wer mit MPLAB hinbekommen? Oder koennt ihr mir eine Alternative nennen?

    Vielen Dank schonmal,
    Kiraminh

  2. #2
    Theoretisch ist das natürlich möglich.....

    Unter diesem link findest du einen ansatz dafür
    http://www.microchipc.com/Hi-Tech_C_multitask/

  3. #3
    Benutzer Stammmitglied
    Registriert seit
    24.10.2007
    Ort
    Loughborough
    Alter
    34
    Beiträge
    53
    Vielen Dank, ich werde mir den mal anschauen.

    Ich habe noch eine andere Frage, moechte aber dafuer keinen neuen Thread aufmachen. Ich sizte jetzt schon an die 5 Tage an einem Problem, dessen Ursache ich nicht finde. Ich versuche ueber UART mit dem Pololu Micro Serial Servo Controller zu kommunizieren. Ich dachte, dass das ganz einfach sei, doch leider habe ich mich wohl getaeuscht.

    In dem angehaengten Code versuche ich UART zu initialisieren, sowie dem Servo Controller quasi eine Geraetenummer zu geben, da ich vier der Teile nutzen werde. Ich habe die Baudrate in den Bereich gesetzt, der im Manual mir angegeben wurde (ich glaube momentan auf ungefaehr 20.000). Lasse ich den Code laufen sagt mir der Servo Controller, er habe keine Baudrate bekommen, empfaengt demnach natuerlich auch keine Signale. Wenn ich die Baudrate hingegen auf ueber 40k setze (ich habe ueber 900k getestet), dann sagt er mir, dass die Baudrate zu langsam sei.

    Kennt irgendwer dieses Phaenomen?

    Hier ist der Code, ich entschuldige mich schonmal fuer die Laenge, ich habe sehr viel kommentiert:

    Code:
    //*****************************************************************
    //* main.c                                                	  *
    //*****************************************************************
    //*                                                               *
    //* Written by:  L J Berger                                       *
    //*              Iensys Ltd	                                      *
    //* Date:        11th March 2007                            	  *
    //* Revision:	 1.00                                             *
    //*****************************************************************
    //                                                                *
    // 	This programm initializes the servo controller. The ID number *
    //  is assigned to the device:                                    *
    //  0 -> The servo controller reacts to the servo no 0-7          *
    //  1 -> The servo controller reacts to the servo no 8-15         *
    //  2 -> The servo controller reacts to the servo no 16-23        *
    //  ...  up to servo no 127
    //*****************************************************************
    
    //*****************************************************************
    // Include Files
    //*****************************************************************
    #include <p30f6014A.h> //device specific header file
    #include <stdlib.h> // for structs being able to refer to itself
    
    //IMPORTANT: Tell the linker to create a 512byte heap. Otherwise
    //			 the dynamic memory allocation cannot be used
    
    //*****************************************************************
    // Config directive to set configuration bits
    //*****************************************************************
    /* The internal clock controlling the execution of instructions is obtained 
       when the clock (from the PLL or directly) is divided by 4.
       Example: Let a 10MHz crystal resonator and PLL 4x are selected. This means
       that the internal clock is 4x10MHz=40MHz. This value is divided by 4 to
       obtain 10MHz (100ns period)
    */
    _FOSC(CSW_FSCM_OFF & XT_PLL16); //Fail safe Clock Monitor Off, eXTernal crystal with PLL 4x
    
    /*Configuration of the Watchdog Timer*/
    _FWDT(WDT_OFF); // Watchdog Timer off
    
    /* FBORPOR is for voltage protection. The proper execution of the programs
       requires a good stability of the power supply. With dsPIC30F one has the
       ability of defining a minimum power supply voltage ensuring proper 
       function of the device. If the supply voltage falls below this limit, the
       internal circuit will reset the microcontroller, wait until the supply 
       voltage returns above the limit, and after the specified power-up delay
       time activate the microcontroller starting the execution of the program 
       from the beginning
    */
    // enable Brown-out Reset at 2.0 Volts, initialize Power up Timer to 64ms,
    // MCLR pin enabled (not used for I/O)
    _FBORPOR(PBOR_ON & BORV_20 & PWRT_64 & MCLR_EN); 
    
    //*****************************************************************
    // Macros
    //*****************************************************************
    #define FCY 7370000				// 7.37MHz crystal in XT PLL 4x
    #define MILLISEC FCY/7370		//definition of a millisecond
    
    //connecting the ports
    #define LED1	PORTDbits.RD4
    #define LED2	PORTDbits.RD5
    #define LED3	PORTDbits.RD6
    #define LED4	PORTDbits.RD7
    /* The LEDs are used to give an error-code:
    RD4 RD5 RD6 RD7 	Error
     0   0   0   0		No Error
     0   0   0   1		Data received fron U2ART
     0   0   1   0		
     0   0   1   1		
     0   1   0   0		Unable to write to queue, because the heap might be full
     0   1   0   1		Unable to delete, queue is empty
    */
    
    //*****************************************************************
    // Definition of global variables and structures
    //*****************************************************************
    //UART Initialisation Flags
    struct{
    	unsigned EnTXInterrupt:1;
    	unsigned TXInterruptMode:1;
    	unsigned Buffer_free:1;
    }UART2Flags;
    
    struct FCFS_queue
    {
    	unsigned data:8;
    	struct FCFS_queue * next;
    };
    struct FCFS_queue * UART2TXReg;
    //*****************************************************************
    // Definition of functions
    //*****************************************************************
    int InitUART(void);
    int InitServoController(void);
    void DelayNms (unsigned int N);
    int queue_add (struct FCFS_queue * head, unsigned int new_data);
    int queue_delete (struct FCFS_queue * head);
    int generalInits(void);
    void UART2Transmission(void);
    void __attribute__((__interrupt__))_U2TXInterrupt(void);
    
    //*************************************************************************
    // Implementation of functions
    //*************************************************************************
    //UART is initialized
    //data  bits has to be either 8 or 9, stop bits either 1 or 2, parity bits either 0 (no parity) 
    //or 1 (odd parity) or 2 (even parity)
    //for more information see Family Reference Manual Section 19 on UART, page 19-3
    //for enabling transmission interrupts set EnTXInterrupt and select Transmission Interrupt Mode
    //as well as use the Interrupt functions which are currently commented out.
    int InitUART(void)
    {
    
    	U2MODEbits.USIDL = 0;		//Continue Operation in Idle mode
    	U2MODEbits.ALTIO = 0;		//Communicate using U2TX and U2RX, not alternate pins
    	U2MODEbits.WAKE = 0;		//Wake-up disabled
    	U2MODEbits.LPBACK = 0;		//Loopback mode disabled
    	U2MODEbits.ABAUD = 0;		//No Autobaud
    	U2MODEbits.PDSEL = 0;		//8-bit data, no parity
    	U2MODEbits.STSEL = 0;		//1 Stop bit
    	
    
    	if (UART2Flags.EnTXInterrupt == 1)
    	{
    		//Clear Interrupt Status Flag for U2TXIF
    		IFS1bits.U2TXIF = 0; 
    		//Setting the Interrupt control bit (U2TXIE) in the Interrupt Enable Control register.
    		IEC1bits.U2TXIE = 1;
    		//Select Transmit Interrupt Mode: 
    		U1STAbits.UTXISEL = UART2Flags.TXInterruptMode;
    	}
    
    	//Baud Rate: UxBRG = FCY/(16*BaudRate)-1. For 20,000: U2BRG = 23
    	//BaudRate has to be between 2000 and 40000 for Pololu Micro Serial Servo Controller
    	U2BRG = 91;
    
    	U2STAbits.UTXBRK = 0; //Transmit Break Bit-pin operates normally
    	
    	//Enable UART2
    	U2MODEbits.UARTEN = 1;
    	//Enable Transmission
    	U2STAbits.UTXEN = 1;
    
    	return 0;
    }
    
    //Setting and Checking Servo Numbers
    int InitServoController(void)
    {
    	if (UART2Flags.Buffer_free)
    	{
    		U2TXREG = 0x80;
    		U2TXREG = 0x02;
    		U2TXREG = 0x00;
    		//UART2Flags.Buffer_free = 0;
    	}
    	else{
    		if (!queue_add(UART2TXReg, 0x80)) //first start byte 
    		{
    			LED2 = 1;
    			return 1; 
    		}
    		if (!queue_add(UART2TXReg, 0x02)) //command to change servo numbers
    		{
    			LED2 = 1;
    			return 1; 
    		}
    		if (!queue_add(UART2TXReg, 0x00)) //servo numbers for this board: 0 -> 0-7, 1 -> 8-15, ...
    		{
    			LED2 = 1;
    			return 1; 
    		}
    	}
    	return 0;
    }
    	
    void DelayNms (unsigned int N)
    {
    	unsigned int j;
    	while(N--)
    		for (j=0;j<MILLISEC;j++);
    }	
    
    //if Interrupts are needed for UART2 Transmission
    /*void __attribute__((__interrupt__))_U2TXInterrupt(void)
    {
    	int counter = 0;
    	if (UART2TXReg != NULL)
    	{
    		while (UART2TXReg != NULL && counter < 3)
    		{
    			U2TXREG = UART2TXReg->data;
    			if (queue_delete(UART2TXReg)) return;
    			counter+=1;
    		}
    		UART2Flags.Buffer_free = 0;
    	}
    	else UART2Flags.Buffer_free = 1;
    	//clearing the Interrupt Status Flag
    	IFS1bits.U2TXIF = 0;		
    }*/
    
    // Add a new element to the end of the queue
    int queue_add (struct FCFS_queue * head, unsigned int new_data)
    {
    	//create new element
    	struct FCFS_queue * temp = (struct FCFS_queue*) malloc(sizeof(struct FCFS_queue));
    	//if the heap is full, temp will just carry the NULL pointer.
    	//to prevent a runtime error this is catched
    	if (temp == NULL) return 1;
    	//if temp is not NULL, the data can be written into the struct.
    	//as this element will be placed at the very end of the queue, 
    	//temp->next can be set to NULL.
    	temp->data = new_data;
    	temp->next = NULL;
    
    	//go to the end of the queue and add the element
    	if (head != NULL)
    	{
    		while (head->next != NULL) head = head->next;
    		head->next = temp;
    	}
    	//if the queue is empty, then just put it there.
    	else head = temp;
    	return 0;	
    }
    
    // Delete the first element of the queue
    int queue_delete (struct FCFS_queue * head)
    {
    	//if head is NULL, no element can be deleted -> ERROR
    	if (head == NULL) 
    	{
    		LED2=1;
    		LED4=1;
    		return 1;
    	}
    	else //there is still at least one element in the queue, that can be deleted
    	{
    		struct FCFS_queue * temp = head; //new pointer to the first element
    		head = head->next; //main pointer of the queue ist shifted one element to the rear
    		free((void*)temp); //free the allocated memory to prevent memory leaks
    	}
    	return 0;
    }
    //General variables and structures are initialised in this function. 
    //It is called at the very beginning of main
    int generalInits(void)
    {
    	//Information for UART Initialisation
    	UART2Flags.EnTXInterrupt = 0; 	// transmission interrupts disabled
    	UART2Flags.TXInterruptMode = 0;	// Interrupt when last character out of the buffer was transferred
    	UART2Flags.Buffer_free = 1; 	// at the beginning of course the buffer is free
    
    	//Initialisation of Transmitter Register for UART2
    	UART2TXReg = NULL;
    
    	return 0;
    }
    
    //This function will be started as a separate task and checks whether there
    //is any data in UART2TXReg to be transmitted and whether the buffer is able 
    //to save this transmission data
    //ONLY SUITABLE FOR MULTITASKING
    /*void UART2Transmission(void)
    {
    	while (1)
    	{
    		if(!U2STAbits.UTXBF && UART2TXReg != NULL)
    		{
    			U2TXREG = UART2TXReg->data;
    			if (queue_delete(UART2TXReg)) return;
    		}
    	}
    }*/
    
    //*****************************************************************
    // MAIN
    //*****************************************************************
    int main (void)
    {
    	//int TaskID_UART2TX = 0;
    	if (generalInits()) return 1;
    	if (InitUART()) return 1;
    	
    	//The task for transmitting via UART cannot be started before 
    	//generalInits and InitUART. Otherwise data will get lost!
    	//ONLY SUITABLE FOR MULTITASKING
    	//TaskID_UART2TX = execi(&UART2Transmission, 0, 0, 10, DEFAULT_STACK_SIZE);
    
    	if (InitServoController()) return 1;
    
    	unsigned int received_data;
    	while (U2STAbits.URXDA)
    	{
    		received_data = U2RXREG;
    		LED4 = 1;
    		DelayNms(1000);
    		LED4= 0;
    	}
    		
    	
    	//ONLY SUITABLE FOR MULTITASKING
    	/*shutdown_task(&TaskID_UART2TX);
    	kill_task(&TaskID_UART2TX);*/
    	
    	//Disable UART2:
    	//U2MODEbits.UARTEN = 0;
    	return 0;
    }
    Ich bedanke mich schon mal fuer die Hilfe!

    Gruesse,
    Kira

  4. #4
    versuchs doch mal mit der von microchip mitgelieferten headerdatei usart.h.... vielleicht hast du bei der initialisierung einen fehler gemacht. Die Funktionen von Micochip gehen nämlich sicher ......

  5. #5
    Benutzer Stammmitglied
    Registriert seit
    24.10.2007
    Ort
    Loughborough
    Alter
    34
    Beiträge
    53
    also, nach einigem Testen habe ich heraus gefunden, dass mein Code richtig ist. Ich habe das Board via COM-Schnittstelle an meinen PC angeschlossen und sobald etwas zu dem Board gesendet wird, schickt das Board "Hello World" ... ganz easy und es funzt auch! Ergo an der Initialisierung kann es nicht liegen.

    Ich werde nun schauen, ob ich hier nicht einen Hardwarefehler meinerseits verursacht habe oder sonst irgendwelche I/O Ports vergessen habe zu definieren.

    Ich melde mich, sobald ich das Problem behoben habe. Wenn ihr in der Zwischenzeit noch weitere Ideen habt, nur zu.

    @Duke: ich schau mal in die usart.h rein. Ich hoffe die ist gut kommentiert, damit ich auch verstehe, was die da gemacht haben.

  6. #6
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    20.08.2004
    Ort
    Unterschleissheim
    Beiträge
    218
    Hallo

    kann es sein, dass der Servo zwar mittels UART angesteuert wird, selber aber nicht 12Volt-Pegel hat, sondern nur 5 Volt ? Dann wäre auch der Pegel falsch. Da RS232 mit +-12Volt arbeitet und das Signal invertiert.

    Gerhard

  7. #7
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    17.08.2004
    Beiträge
    1.065
    Wie genau ist deine Taktquelle? Unter umständen könnte der Rechner Fehlertoleranter sein als das Servoboard. Hast du alle Zeichen mitgesendet, also auch Zeilenende, jenachdem was das Servoboard braucht?
    ...

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •