Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //Chip info:
- AT90CAN128 @16MHz
- Problem:
- The program jumps to memcpy in the main() randomly after the first call to renderTimeTable()
- placing any code in the place of memcpy that involve copying one array to the other causes the issue
- //main.c
- #include <avr/io.h>
- #include <avr/interrupt.h>
- #include <avr/sleep.h>
- #include <util\delay.h>
- #include <string.h>
- #include "pwm.h"
- #include "spi.h"
- const int MOTOR_FOOT = 0;
- const int MOTOR_LEG = 1;
- const int MOTOR_BODY = 2;
- int main(void)
- {
- //High-bit indicates an output
- DDRA = 0xFF;
- DDRB = 0x00;
- DDRC = 0xFF;
- DDRD = 0xFF;
- PORTA = 0x00;
- PORTB = 0x00;
- PORTC = 0x00;
- PORTD = 0x00;
- //Initialize counter interrupt, to execute @100kHz
- pwm_init();
- //Initialize SPI
- spi_init();
- //Enable interrupts
- sei();
- //Build rendertable for the pwm
- uint8_t temp[] = {
- 4,50,100,150,200,250,0,0
- };
- renderTimeTable(temp);
- while(1)
- {
- while(!buffer_finished){}
- //buffer_finished = 0;
- uint8_t portbuffer[8];
- memcpy((void*) spi_buffer, portbuffer,8);//<---PROBLEM IS HERE, it jumps to this line after the first renderTimeTable() used above
- //Parse buffer and write pwm
- renderTimeTable(portbuffer);
- }
- }
- //pwm.h
- #ifndef HEADER_GUARD_PWM
- #define HEADER_GUARD_PWM
- void pwm_init(void);
- void renderTimeTable(uint8_t[8]);
- volatile uint8_t timetable[200];
- #endif
- //pwm.c
- #include <avr/io.h>
- #include <avr/interrupt.h>
- #include <string.h>
- #include "pwm.h"
- void pwm_init(void)
- {
- //Initialize the timer for 100kHz
- //Set prescaler: none
- TCCR1B |= (1 << CS10);
- //Waveformgenerator mode: CTC
- TCCR1B |= (1 << WGM12);
- //Counter compare value: 160
- OCR1A = (uint16_t) 160;
- //Reset current counter
- TCNT1 = 0;
- //Enable interrupt for counter compare
- TIMSK1 |= (1 << OCIE1A);
- }
- //Store timetable
- volatile uint8_t timetable[200];
- volatile uint8_t debug[8];
- //Render a timetable for a single port, angles has to have a length of 8!
- void renderTimeTable(uint8_t angles[8])
- {
- uint8_t _timetable[200];
- for(uint8_t time=0;time<200;time++)
- {
- _timetable[time] = 0x00;
- for(uint8_t i=0;i<8;i++)
- {
- _timetable[time] |= (time < angles[i])<<i;
- }
- }
- for(int i =0;i<200;i++)
- {
- timetable[i] = _timetable[i];
- }
- }
- //Keep track of progression in PWM over 20ms -> 20000 vals;
- volatile uint16_t pwm_pointer = 0;
- //Timer interrupt @100kHz
- ISR (TIMER1_COMPA_vect)
- {
- PORTC = 0xFF;
- pwm_pointer++;
- if (pwm_pointer<50)
- {
- PORTD = 0xFF;
- }
- else if (pwm_pointer<250)
- {
- PORTD = timetable[pwm_pointer - 50];
- }
- else
- {
- PORTD = 0x00;
- if (pwm_pointer>=2000)
- {
- pwm_pointer = 0;//20ms * 100/ms
- }
- }
- PORTC = 0x00;
- }
- //spi.h
- /*
- * File: simple SPI routines for AVR
- * Author: Tuomas Nylund ([email protected])
- * Website: http://tuomasnylund.fi
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
- #ifndef SPI_H_
- #define SPI_H_
- #include <avr/io.h>
- #define SPI_DDR DDRB
- #define SPI_MOSI_BIT PB2
- #define SPI_SCK_BIT PB1
- #define SPI_CS_BIT PB0
- #define SPIMODE0 (0<<CPHA)
- #define SPIMODE1 (1<<CPHA)
- #define SPIMODE2 (2<<CPHA)
- #define SPIMODE3 (3<<CPHA)
- #define LSB_FIRST (1<<DORD)
- #define MSB_FIRST (0<<DORD)
- #define CLOCKDIV4 (0<<SPR0)
- #define CLOCKDIV16 (1<<SPR0)
- #define CLOCKDIV64 (2<<SPR0)
- #define SPI_BUFFER_SIZE 18
- void spi_init(void);
- void spi_send_byte(uint8_t data);
- uint8_t spi_read_byte(void);
- volatile uint8_t buffer_finished;
- volatile uint8_t spi_buffer[SPI_BUFFER_SIZE];
- #endif
- //spi.c
- #include <avr/io.h>
- #include <avr/interrupt.h>
- #include <string.h>
- #include "spi.h"
- void spi_init(void){
- //Set MoSi as input, we will only receive
- SPI_DDR |= (1<<SPI_MOSI_BIT);
- //Enable SPI and SPI interrupts
- SPCR = (1<<SPE) | (1<<SPIE);
- }
- void spi_send_byte(uint8_t data){
- SPDR = data;
- //Wait for stuff to be finished
- while(!(SPSR & (1<<SPIF)));
- }
- uint8_t spi_read_byte(void){
- SPDR = 0x00;
- while(!(SPSR & (1<<SPIF)));
- return SPDR;
- }
- //Buffer to store SPI data in
- volatile uint8_t spi_buffer[SPI_BUFFER_SIZE];
- //Pointer to indicate progression in the buffer
- volatile uint8_t buffer_pointer = 0;
- //Boolean flag to indicate a message was fully received
- volatile uint8_t buffer_finished = 0;
- //Receive SPI commands
- ISR(SPI_STC_vect)
- {
- //Read received byte
- uint8_t received = SPDR;
- SPDR = 0x00;
- if (received==0x00)
- {
- buffer_pointer = 0;
- }
- spi_buffer[buffer_pointer] = received;
- //Progress the pointer, and wrap if neccessary
- buffer_pointer++;
- if (buffer_pointer>=SPI_BUFFER_SIZE)
- {
- buffer_pointer = 0;
- buffer_finished = 1;
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment