No se puede manipular la matriz con atmega8

1

Soy bastante nuevo en la programación de AVR y actualmente tengo algunos problemas con los arreglos.

Estoy intentando escribir un código Arduino que se ejecutará en un Atmega32u4. El objetivo es comunicarse con un servo Dynamixel AX12-A (Atmega8) que tiene el firmware disponible públicamente.

Antes de escribir este código de Arduino, quería jugar con el código de firmware y me di cuenta de que no podía manipular matrices.

He modificado el firmware para que el LED en AX12-A parpadee constantemente. Aquí vienen algunas líneas de código que hacen que el Atmega8 se bloquee (sin parpadear):

uint8_t testArray[5] = {0x42, 0, 0, 0, 0}; 
SendMSG(testArray, 1, 0xFE); // works (the LED is constantly blinking)
// SendMSG(testArray, 0, 0xFE); // works as well

La función SendMsg es solo una escritura en serie. testArray son los datos para escribir, 1 la longitud y 0xFE es el dispositivo al que se deben enviar los datos.

void SendMSG(uint8_t *Array, uint8_t length,uint8_t DestinationID)

Para comprobar qué está enviando el servo, escribí un pequeño código Arduino cargado en un Leonardo para "espiar" la comunicación en serie. Esto es lo que obtengo con el fragmento de trabajo:

Response: AA // packet header
Response: 3  // packet length
Response: FE // destination ID
Response: FF // origin ID
Response: 42 // data
Response: BA // checksum
(and this sequence is repeated again and again)

Esto es exactamente lo que se supone que debo recibir. Aquí hay un fragmento de código que no funciona (el LED no parpadea):

uint8_t testArray[5] = {0x42, 0x02, 0, 0, 0};
SendMSG(testArray, 1, 0xFE); // doesn't work
// SendMSG(testArray, 0, 0xFE); // doesn't work either

Y no veo nada en la comunicación en serie usando el "espía en serie" anterior.

Y aún más sorprendente:

uint8_t u8Data[50];   // define at begin of main
(...)
u8Data[0] = 3; // this line make the code crash (no blinking)

(...)
if(u8Data[0]==BROADCAST_ID)
(...)
if(u8Data[0]==MY_ID)

Así que tengo una matriz definida y CUALQUIER modificación en ella la hará fallar. Tenga en cuenta que no estoy haciendo nada en esa matriz, excepto que verifico si su primer valor es igual a BROADCAST_ID (= 255) o MY_ID (= 1 o -1 si es un error). ¿Cómo sé que esta línea específica hace que mi código se bloquee? Porque si lo comento, mi LED parpadea normalmente.

Como puede adivinar, la programación se vuelve muy limitada cuando no puede lograr esas operaciones triviales.

Realmente no entiendo por qué sucede esto. Tal vez esto venga del Makefile utilizado en el proyecto github? (Tenga en cuenta que incluso si el nombre del proyecto menciona explícitamente atmega328p, el archivo Makefile parece estar diseñado para Atmega8).

Nota: Para actualizar mi Atmega8, compilé mi código utilizando Makefile en el proyecto github anterior y luego usé RoboPlus para cargar en el AX12-A (instrucciones al final de esta página).

Código completo:

/*************************************************
Firmware developed for AX12 servo
ATMega8 processor at 16MHz
by: Ricardo Marinheiro
February 2011
robosavvy
Move Interactive
*************************************************

Changes
V1.0 to V1.2
This version bugs fix:
 - Serial buff reset on test to Message Length keeper and not to buff Length

Improves:
 - Led does not fade, short fast blinks.
 - Fail safe counter created to avoid break on cycling for position,
   when missing previouse messages from previouse servos on chain.
 - Controlling servos just by PWM and cycling for position, the frame, now possible at least at 600fps
 - Fail safe created for speed up syncronization on frame receiving scrambling.

*************************************************/
#include <util/delay.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <ctype.h>
#include <stdbool.h>

#include "Motor.h"
#include "UtilsAndDefines.h"
#include "Serial.h"
#include "Control.h"
#include "Eprom.h"





#define INIT_DELAY 10 //ms


#define RAMVarSize (EEVarSize+0x0007)
#define GoalPositionLow_Addr    (EEVarSize+0)
#define GoalPositionHi_Addr     (EEVarSize+1)
#define GoalSpeed_Addr          (EEVarSize+2)
#define TemperatureLow_Addr     (EEVarSize+3)
#define TemperatureHi_Addr      (EEVarSize+4)
#define PWMLow_Addr             (EEVarSize+5)
#define PWMHi_Addr              (EEVarSize+6)

// #define true                     1
// #define false                    0


uint16_t GoalPos=0;
uint16_t GoalSpeed=0;
uint16_t PreviouseGoalPos=0;
uint16_t GoalPWM=0;
uint16_t PreviouseGoalPWM=0;

uint16_t DelayMs=0;


void RAMSave (uint8_t address, uint8_t data)
{
    uint16_t temp=data;
    // if you need to have any variables on ram that can be dynamicly configured
    switch (address)
    {
        case GoalPositionLow_Addr:
            GoalPos = ((GoalPos&0xFF00)+temp);
        break;

        case GoalPositionHi_Addr:
            GoalPos = ((GoalPos&0xFF)+(temp<<8));
        break;

        case GoalSpeed_Addr:
            GoalSpeed = data;
        break;

        case PWMLow_Addr:
            GoalPWM=((GoalPWM&0xFF00)+temp);
            PreviouseGoalPWM=GoalPWM+1;
        break;

        case PWMHi_Addr:
            GoalPWM=((GoalPWM&0xFF)+(temp<<8));
            PreviouseGoalPWM=GoalPWM+1;
        break;
    }
}

uint8_t RAMGet (uint8_t address)
{
    // if you need to have any variables on ram that can be dynamicly configured
    uint16_t temp=0;

    switch (address)
    {
        case GoalPositionLow_Addr:
            temp=Position;
            //LED_ON;
            return (temp&0xFF);
        break;

        case GoalPositionHi_Addr:
            temp=Position;
            return ((temp&0xFF00)>>8);
        break;

        case GoalSpeed_Addr:
            temp=Velocity;
            return (temp&0xFF);
        break;

        case TemperatureLow_Addr:
            temp=Temperature;
            return (temp&0xFF);
        break;

        case TemperatureHi_Addr:
            temp=Temperature;
            return ((temp&0xFF00)>>8);
        break;

        case PWMLow_Addr:
            temp=(GoalPWM&0xFF);
        break;

        case PWMHi_Addr:
            temp =((GoalPWM&0xFF)>>8);
        break;
    }
    return temp;
}


#define serviceRoutineReset 6
#define CycleFailSafeReplyDelay 2

int main (void)
{

    uint8_t u8Data[50];
    uint8_t u8BusInitiated=0;
    uint8_t u8ID_Previouse=0;
    uint8_t u8Master_Id=0;
    uint8_t u8SendCycle=0;
    int16_t i16Temp=0;
    uint8_t u8ChangedRom=0;
    uint8_t serviceRoutineCounter=0;
    uint8_t sreg;
    uint8_t u8PreviousCount=0;
    uint16_t LedCounter=0;
    uint16_t LedCounterPWM=3000;
    uint16_t u8Counter=0;

    uint8_t FlashingCounter = 0;
    // uint8_t CycleCounter = 0;
    // uint8_t CycleCount = 3;                  // number of times ID will be displayed by LED
    uint8_t PauseTime = 3;                  // pause time is three flash



    #if defined __AVR_ATmega8__
    WDTCR=0;
    #elif defined __AVR_ATmega328P__
    WDTCSR=0;
    #endif

    Led_Dir |= Led;
    LED_OFF;

    EELoadVars();  // load default variables from EEProm

    InitMotor();
    InitControl();
    //InitSerial((uint16_t)UART_BAUD);
    InitSerial(UART_BAUD);

    sei();

    uint8_t testString[5] = {0x42, 0, 0, 0, 0};

// message composition
// header  length destine devID  Origin_ID  data1   data2         dataN   CRC
// [0xAA]  [0xnn]      [id]       [MY_ID]  [0xd1]  [0xd1]  [...] [0xdn]  [0xzz]
//                \____________________ length _______________________/
//         \________________________ crc _____________________________/
// Length is the data that we can read from the buffer once get msg just assure the message integrity by length and CRC nothing else.


    SetFreeweeling(1000);
    while(1) 
    {

        if(LedCounter==0) {
            LED_ON;
            SendMSG(testString, 2, 0xFE);
        }



        if(LedCounter==LedCounterPWM)
            LED_OFF;

        LedCounter++;


        if(serviceRoutineCounter==0)
        {
            if(SerialPWM != PreviouseGoalPWM)
            {
                RAMSave(PWMLow_Addr,(SerialPWM&0xFF)); // save data to RAM
                RAMSave(PWMHi_Addr,(SerialPWM>>8)); // save data to RAM
                SetFreeweeling(GoalPWM);
                PreviouseGoalPWM=GoalPWM;
            }

            //TimerInterruptServiceRoutine();
            _Control_();

            if(DelayMs)
                DelayMs--;

            //TimerIntON=0;
            serviceRoutineCounter=serviceRoutineReset;
        }
        else
            serviceRoutineCounter--;

        SendChar();
        i16Temp = GetMSG(u8Data,0,3,0);
//#########################################     START COMMAND INTERPRETER   ###################################################################
        if(i16Temp>0)// data avaliable
        {


            if(u8Data[0]==BROADCAST_ID)//destination
            {


                if(u8Data[2]==AX12_START)   /// start or restart the bus
                {
                    u8Master_Id = u8Data[1];
                    u8BusInitiated=1;
                    u8ID_Previouse=0;
                    DelayMs=(MY_ID*INIT_DELAY*10);
                }
                else
                if(u8Data[2]==AX12_WRITE)  /// write
                {

                    i16Temp-=4; // take out the length of destineID + originID + Command + address_of_writing
                    GetMSG(&u8Data[1],3,1,0); //get the address
                    u8Data[2]=4;
                    while(i16Temp)
                    {
                        GetMSG(&u8Data[0],u8Data[2]++,1,0); //get the data
                        if(u8Data[1]<EEVarSize) // test if address is from eeprom
                        {
                            u8ChangedRom=1;
                        //  sreg=SREG;
                            cli();
                            EESave(u8Data[1]++,u8Data[0]); // save data to eeprom
                    //      SREG=sreg;
                            sei();
                        }
                        else
                        if(u8Data[1]<RAMVarSize) // test if address if from RAM
                        {
                            RAMSave(u8Data[1]++,u8Data[0]); // save data to RAM
                        }
                        i16Temp--;
                    }

                    if(GoalPos!=PreviouseGoalPos)
                    {
                        PreviouseGoalPos=GoalPos;
                        SetPosition (GoalPos,GoalSpeed, 100, 0);
                        SerialPWM=GoalPWM=PreviouseGoalPWM=1000;
                    }

                    if(GoalPWM!=PreviouseGoalPWM)
                    {
                        SetFreeweeling(GoalPWM);
                        SerialPWM=PreviouseGoalPWM=GoalPWM;
                        PreviouseGoalPos=0;
                        GoalPos=0;
                    }

                    if(u8ChangedRom)
                    {
                    //  sreg=SREG;
                        cli();
                        EELoadVars();
                    //  SREG=sreg;
                        sei();
                        InitSerial(UART_BAUD);
                        u8ChangedRom=0;
                    }
                    //no reply to Master once is a broadcast


                }
                else
                if(u8Data[2]==AX12_SYNC_WR)   /// sync write
                {
                    // do nothing

                    // temp // total packet length
                    GetMSG(u8Data,3,2,0);
                    //data[0];  // is the adress where to start writing
                    //data[1];  // is the amount of data to write

                    GetMSG(&u8Data[2],6,u8Data[1],1); // read to *data[2] starting on 5 a length of data[1]+1*(ID)
                    //write data to memory eeprom or ram and end
                    for(u8Counter=0;u8Counter<u8Data[1];u8Counter++)
                    {
                        if(u8Data[0]<EEVarSize) // test if address is from eeprom
                        {
                            u8ChangedRom=1;
                        //  sreg=SREG;
                            cli();
                            EESave(u8Data[0]++,u8Data[2+u8Counter]); // save data to eeprom
                        //  SREG=sreg;
                            sei();
                        }
                        else
                        if(u8Data[0]<RAMVarSize) // test if address if from RAM
                        {
                            RAMSave(u8Data[0]++,u8Data[2+u8Counter]); // save data to RAM
                        }
                    }

                    if(GoalPos!=PreviouseGoalPos)
                    {
                        PreviouseGoalPos=GoalPos;
                        SetPosition (GoalPos,GoalSpeed, 100, 0);
                        SerialPWM=GoalPWM=PreviouseGoalPWM=1000;
                    }

                    if(GoalPWM!=PreviouseGoalPWM)
                    {
                        SetFreeweeling(GoalPWM);
                        SerialPWM=PreviouseGoalPWM=GoalPWM;
                        PreviouseGoalPos=0;
                        GoalPos=0;
                    }

                    if(u8ChangedRom)
                    {
                    //  sreg=SREG;
                        cli();
                        EELoadVars();
                    //  SREG=sreg;
                        sei();
                        InitSerial(UART_BAUD);
                        u8ChangedRom=0;
                    }
                }
                else
                if(u8Data[2]==AX12_CYCLE)    /// start the sending cycle
                {
                    if(u8BusInitiated==2) // if the BUS is initiated
                    {
                        u8Master_Id = u8Data[1];
                        if(u8ID_Previouse==0) // means  that there is no servos before me i'm the first
                        {
                            u8Data[0] = ((Position)>>8); //MSB
                            u8Data[1] = Position; //LSB
                            SendMSG(u8Data,2,u8Master_Id);

                            u8SendCycle=0;
                        }
                        else
                        {
                            u8SendCycle=1;
                            DelayMs=(CycleFailSafeReplyDelay*UART_BAUD*u8PreviousCount);
                        }
                    }
                    //else do nothing
                }
                else
                if(u8Data[2]==AX12_RESET)
                {
                //  sreg=SREG;
                    cli();
                    EEPromReset();
                //  SREG=sreg;
                    sei();
                    InitSerial(UART_BAUD);
                }
                else
                {
                    u8Master_Id = u8Data[1];
                    // no recognised command
                    u8Data[0] = AX12_NOK;  // send NOK
                    SendMSG(u8Data,1,u8Master_Id);
                }
            }
            else
            if(u8Data[0]==MY_ID)   //destination is Me
            {


                u8Master_Id = u8Data[1];
                if(u8Data[2]==AX12_WRITE)  /// write
                {
                    i16Temp-=4; // take out the length of destineID + originID + Command + address_of_writing
                    GetMSG(&u8Data[1],3,1,0); //get the address

                    if((i16Temp+u8Data[1])>(RAMVarSize)) // if address+length > RAMVarSize+EEVarSize   send NOK
                    {
                        // no recognised command
                        u8Data[0] = AX12_NOK;  // send NOK
                        SendMSG(u8Data,1,u8Master_Id);
                    }
                    else
                    {
                        u8Data[2]=4;

                        while(i16Temp)
                        {
                            GetMSG(&u8Data[0],u8Data[2]++,1,0); //get the data

                            if(u8Data[1]<EEVarSize) // test if address is from eeprom
                            {
                                u8ChangedRom=1;
                            //  sreg=SREG;
                                cli();
                                EESave(u8Data[1]++,u8Data[0]); // save data to eeprom
                            //  SREG=sreg;
                                sei();
                            }
                            else
                            if(u8Data[1]<RAMVarSize) // test if address if from RAM
                            {
                                RAMSave(u8Data[1]++,u8Data[0]); // save data to RAM
                            }
                            i16Temp--;
                        }

                        if(GoalPos!=PreviouseGoalPos)
                        {
                            PreviouseGoalPos=GoalPos;
                            SetPosition (GoalPos, GoalSpeed, 100, 0);
                            SerialPWM=GoalPWM=PreviouseGoalPWM=1000;
                        }

                        if(GoalPWM!=PreviouseGoalPWM)
                        {

                            SetFreeweeling(GoalPWM);
                            SerialPWM=PreviouseGoalPWM=GoalPWM;
                            PreviouseGoalPos=0;
                            GoalPos=0;
                        }

                        // Load the variables from EEPROM

                        if(u8ChangedRom)
                        {
                        //  sreg=SREG;
                            cli();
                            EELoadVars();
                        //  SREG=sreg;
                            sei();

                            InitSerial(UART_BAUD);
                            u8ChangedRom=0;
                        }

                        u8Data[0] = AX12_OK;  // send OK
                        SendMSG(u8Data,1,u8Master_Id);
                    }

                }
                else
                if(u8Data[2]==AX12_READ)
                {
                    GetMSG(&u8Data[2],3,2,0); //get the address and length

                    if((u8Data[2]+u8Data[3])>(RAMVarSize)) // if address+length > RAMVarSize+EEVarSize   send NOK
                    {
                        // no recognised command
                        u8Data[0] = AX12_NOK;  // send NOK
                        SendMSG(u8Data,1,u8Master_Id);
                    }
                    else
                    {

                        for(i16Temp=0; i16Temp<u8Data[3] ; i16Temp++)
                        {

                            if(u8Data[2]<EEVarSize) // test if address is from eeprom
                            {
                            //  sreg=SREG;
                                cli();
                                u8Data[4+i16Temp] = EEGet(u8Data[2]+i16Temp); // get data from eeprom
                                //SREG=sreg;
                                sei();

                            }
                            else
                            if(u8Data[2]<RAMVarSize) // test if address if from RAM
                            {
                                u8Data[4+i16Temp] = RAMGet(u8Data[2]+i16Temp); // get data from RAM
                            }
                        }


                        SendMSG(&u8Data[4],i16Temp,u8Master_Id); // send data to the requester
                    }

                }
                else
                if(u8Data[2]==AX12_PING)
                {
                    //LED_ON;
                    u8Data[0] = AX12_PING;
                    SendMSG(u8Data,1,u8Master_Id);
                }
                else
                if(u8Data[2]==AX12_RESET)
                {
                    //sreg=SREG;
                    cli();
                    EEPromReset();
                    //SREG=sreg;
                    sei();
                    InitSerial(UART_BAUD);
                    u8Data[0] = AX12_PING;
                    SendMSG(u8Data,1,u8Master_Id);
                }
                else
                {
                    // no recognised command
                    u8Data[0] = AX12_NOK;  // send NOK
                    SendMSG(u8Data,1,u8Master_Id);
                }

            }
            else
            if(u8Data[1]==u8ID_Previouse) // previouse device sent packet its my turn now
            {
                if(u8BusInitiated==2)
                {
                    if(u8SendCycle==1)
                    {
                        u8SendCycle=0;

                        u8Data[0] = ((Position)>>8); //MSB
                        u8Data[1] = Position; //LSB
                        SendMSG(u8Data,2,u8Master_Id);
                    }
                }
            }
            else
            {   // in here we can receive data from other servos


                if(u8BusInitiated==1) // get the previouse ID to know the place in the line
                {
                    u8ID_Previouse = u8Data[1];
                    u8PreviousCount++;
                }
            }

            // free buffer
            GetMSG(0,0,0,1);

        }
//#########################################     END COMMAND INTERPRETER   ###################################################################

        if(u8BusInitiated==1)
        {
            if(DelayMs==0) // our turn to send the data packet for ping of initiation
            {

                u8Data[0] = AX12_PING;
                SendMSG(u8Data,1,u8Master_Id);
                u8BusInitiated=2;
            }
        }
        else if((u8BusInitiated==2)&&(u8SendCycle==1))
        {
            if(DelayMs==0)
            { // this is a fail safe, in case of missing the pack from the previouse servo, does not break the reply chain to the master
                u8SendCycle=0;
                u8Data[0] = ((Position)>>8); //MSB
                u8Data[1] = Position; //LSB
                SendMSG(u8Data,2,u8Master_Id);
            }
        }
    }





}

Serial.c (para SendMSG ())

  /*************************************************
Firmware developed for AX12 servo
ATMega8 processor at 16MHz
by: Ricardo Marinheiro
February 2011
robosavvy
Move Interactive
*************************************************/
#include <util/delay.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <ctype.h>
#include "UtilsAndDefines.h"
#include "Serial.h"
#include "Eprom.h"




// message composition
// header  length destine devID  Origin_ID  data1   data2         dataN   CRC
// [0xAA]  [0xnn]      [id]       [MY_ID]  [0xd1]  [0xd1]  [...] [0xdn]  [0xzz]
//                \____________________ length _______________________/
//         \________________________ crc _____________________________/




uint8_t DataOut[bufferSize+1];
uint8_t DataOutEndPointer=0;
uint8_t DataOutStartPointer=0;
uint8_t DataOutDiffPointer=0;

uint8_t DataIn[2][bufferSize2+1];
uint8_t DataInLen[2]={0,0};
uint8_t DataInBufSelec = 0;


extern uint16_t SerialPWM =0;


void SendMSG(uint8_t *Array, uint8_t length,uint8_t DestinationID)
{
    uint8_t temp = 0xAA; // header
    uint8_t calcCRC=0;  

    SendData(&temp,1);

    temp = (length+2); // data length plus 2 that is the ID + MY_ID length
    calcCRC= crc(&temp, 1, 0); // CRC
    SendData(&temp,1);

    temp = DestinationID;
    calcCRC += crc(&temp, 1, 0); // CRC
    SendData(&temp,1); // ID

    temp = MY_ID;
    calcCRC += crc(&temp, 1, 0); // CRC
    SendData(&temp,1); // MY ID

    SendData(Array,length); //data
    calcCRC +=crc(Array, length, 0); // CRC

    SendData(&calcCRC,1);
}



int8_t GetMSG(uint8_t *Array,uint8_t Start,uint8_t Length, uint8_t free)
{
    static uint8_t selector=0;
    static uint8_t length=0;
    static uint8_t usingMessage=0;

    if(usingMessage==0)
    {
        cli();
        selector=(1-DataInBufSelec);
        if((DataInLen[selector] != 0) && (Length>0))
        {
            if((Start+Length) > DataInLen[selector])
            {
                free=1;
            }
            else
            {
                usingMessage=1;
                length = DataInLen[selector];           
                DataInLen[selector]=0xFF;  /// place 0xFF on the data length so on getChar() no overrite to any data is done,
                                               /// forcing  to rewrite to the same buffer again once this is being used
                sei();
                memcopy(Array,(DataIn[selector]+Start),Length);
            }
        }
        sei();
    }
    else
    {
        if(Length>0)
        {
            if((Start+Length) > length)
            {
                free=1;
            }
            else
            memcopy(Array,(DataIn[selector]+Start),Length);
        }

        if(free==1) //once free is set, reset the buffer to be avaliable
        {
            length=DataInLen[selector]=0x0;
            usingMessage=0;
        }
    }
    return length;
}




uint16_t SendData(uint8_t *Array, uint8_t length)
{
    uint8_t counter=0;

    for(counter=0;counter<length;counter++)
    {
        DataOut[DataOutEndPointer++]=*Array++;

        if(DataOutEndPointer==bufferSize)
        {
            DataOutEndPointer=0;
        }

        if(DataOutDiffPointer<bufferSize)
        {
            DataOutDiffPointer++;
        }
        else
        {
            length=0;
        }
    }

    return counter;
}





void InitSerial(uint16_t SerialSpeed)
{
    HalfDuplexTransceiver_Dir  |=   (HalfDuplexTransceiver_PinOUT|HalfDuplexTransceiver_PinIN);

    UCSRA = bit(U2X); //using double speed
    UCSRB = (bit(RXCIE)|/*bit(UDRIE)|*/bit(RXEN)|bit(TXEN)/*|bit(TXCIE)*/); // enable RX and TX interrupt RX and TX

    UCSRB &= ~(bit(RXB8)|bit(TXB8)|bit(UCSZ2));   // disable  TX and RX nineth bit and reset UCSZ2, this is used with UCSZ1 and UCSZ0 to determine the length of the word
    UCSRC = ~(bit(UMSEL)|bit(UPM0)|bit(UPM1)|bit(USBS)|bit(UCPOL));//disable parity and set assyncronous, set 1stopBit and polarity on rising edge
    UCSRC |= (bit(UCSZ1)|bit(UCSZ0)|bit(UCPOL));
    //   UCSZ2=0 UCSZ1=1 UCSZ0=1 => 8bit length
    UBRRH = ((SerialSpeed)>>8);   //set baud counter high
    UBRRL = (SerialSpeed&0xFF);             //set baud counter low                                                                                                                          
    UCSRA|=bit(TXC);
}





void PrintDecimal (int Data)
{

    volatile uint16_t counter=5, firstNum=0, result=0, temp=0;
    volatile uint16_t divisor=10000;

    if(Data>0)
    {
        while(counter--)
        {
            result=Data/divisor;
            if( (result>0) || (firstNum==1))
            {
                firstNum=1;
                result+=0x30;
                SendData((uint8_t *)&result,1);
                //while(!SendChar());
                result-=0x30;
            }
            Data-=(result*divisor);
            divisor=(divisor/10);
        }
    }
    else
    if(Data<0)
    {
        temp=(Data-0xFFFE);
        while(counter--)
        {
            result=temp/divisor;
            if( (result>0) || (firstNum>0))
            {
                firstNum++;
                result+=0x30;
                if(firstNum==1)
                {
                    SendData("-",1);
                    //while(!SendChar());
                }

                SendData((uint8_t *)&result,1);
                //while(!SendChar());
                result-=0x30;
            }
            Data-=(result*divisor);
            divisor=(divisor/10);
        }
    }
    else
    {
        result=0x30;
        SendData((uint8_t*)&result,1);
    }

}


#define resetTim_Default bufferSize


uint8_t GetChar(void)
{
    (body size reached...)
}

int8_t SendChar(void)
{
    static uint8_t readWrite=0; // this exists only to spare some time on the continuous polling

    if(UCSRA&bit(UDRE))
    {

        if(DataOutDiffPointer>0)
        {
            if(readWrite==0)
            {
                readWrite=1;
                SET_WRITE;
            }
            UDR=DataOut[DataOutStartPointer];   

            DataOutStartPointer++;
            DataOutDiffPointer--;

            if(DataOutStartPointer==bufferSize)
                DataOutStartPointer=0;

            return 1;
        }
    }

    if(DataOutDiffPointer==0)
    {
        if(UCSRA&bit(TXC))
        {
            readWrite=70;
            while(readWrite--){asm("nop");} // this is just to allow the  sending of the last byte complitly before disconnect the reading
            readWrite=0;
            SET_READ;
            UCSRA|=bit(TXC);
        }
        else
        return 0;// mean that ther's nothing to be sent
    }
    else  // mean that uart hard buff is full and no byte could be sent there
    {
        return -1;
    }
}

#if defined __AVR_ATmega8__
ISR (USART_RXC_vect)
#elif defined __AVR_ATmega328P__
ISR (USART_RX_vect)
#endif
{

    GetChar();

}

Serial.h:

#if defined __AVR_ATmega328P__

#endif

#define AX12_PING       0x01
#define AX12_READ       0x02
#define AX12_WRITE      0x03
#define AX12_OK         0x04
#define AX12_MUTE       0x05
#define AX12_START      0x06
#define AX12_CYCLE      0x07
#define AX12_NOK        0x08
#define AX12_RESET      0x09
#define AX12_SYNC_WR    0x83

#define MASTER_ID       254
#define BROADCAST_ID    255

#define HalfDuplexTransceiver_Port      PORTD
#define HalfDuplexTransceiver_Dir       DDRD
#define HalfDuplexTransceiver_PinOUT    BIT7
#define HalfDuplexTransceiver_PinIN     BIT6

#define Baud9600    207
#define Baud57600   34
#define Baud115200  16
#define Baud500000  3
#define Baud1000000 1
#define Baud2000000 0

#define bufferSize 200
#define bufferSize2 250

#define TXByteEmpty (((UCSRA&bit(UDRE))>0)?1:0)
#define TXBuffEmpty (((UCSRA&bit(TXC))>0)?1:0)

#define SET_WRITE HalfDuplexTransceiver_Port|=HalfDuplexTransceiver_PinOUT;HalfDuplexTransceiver_Port&=~HalfDuplexTransceiver_PinIN;

#define SET_READ HalfDuplexTransceiver_Port&=~HalfDuplexTransceiver_PinOUT;HalfDuplexTransceiver_Port|=HalfDuplexTransceiver_PinIN;

uint16_t SerialPWM;

/**
*@brief Function to send raw data to the bus
*@var Array Pointer to the array of data to be sent to the bus
*@var length Length of the data to be sent
*@return none
*/
uint16_t SendData(uint8_t *Array, uint8_t length);

/**
*@brief Function to init all the serial communication system, prepare buffers, port baudrate etc
*@var SerialSpeed Predifined value (on serial.h) to attribute to the serial port prescaler to work at the desired speed
*@return none
*/
void InitSerial(uint16_t SerialSpeed);

/**
*@brief Utility Function to print ascii coded decimal values to the bus
*@var Data value to be printed
*@return none 
*/
void PrintDecimal (int Data);

/**
*@brief Function to be called by main working as polling to the incomming data, and unpack messages from bus
*@var none
*@return 1 if any data on comm port buffer\n0 if none
*/
uint8_t GetChar(void);

/**
*@brief Function to be called by main working as polling to the outgoing data
*@var none
*@return 1 if byte sent to hard buff\n -1 if hard buff full and no byte sent there\n 0 if uart buff empty
*/
int8_t SendChar(void);

/**
*@brief Function to get data message incoming from bus, contained on messages buffer
*@var Array Pointer to the container where to copy data to
*@var Start Buffer postition where to start getting the message
*@var Length Number of bytes to read
*@var free Set buffer free for new messages
*@return 0 if no data message ready to read\n -1 if the Start plus length are bigger than message length\nMessage length if avaliable data to read
*/
int8_t GetMSG(uint8_t *Array,uint8_t Start,uint8_t Length, uint8_t free);

/**
*@brief Function to pack data and send it in a message pack to the bus
*@var Array Pointer to the array of data to be sent
*@var length Length of data to be send
*@return none
*/
void SendMSG(uint8_t *Array, uint8_t length, uint8_t DestinationID);
    
pregunta erenaud

0 respuestas

Lea otras preguntas en las etiquetas