I am interfacing LM35 with Atmega8. To display digits I use 7 segment LED anode display that I connect to AVR both ends (it handles it without transistors so why not). Strange thing happens:
res value after assigning it from adc is 237 (23.7 degrees). I want to print on my display the first digit (2).
If I leave last line in the while commented out, the display first shows digit 2 correctly but after the first delay it shows 1 instead of 2. Otherwise I get correctly digit 2. Why is this happening?
#ifndef F_CPU
#define F_CPU 1000000UL
#endif // F_CPU
#include <avr/io.h>
#include <util/delay.h>
#define DELAY_IN_MS 500 /* 0.5 sec */
int numbers[] = {
0b01000000,
0b01110011,
0b00100100,
0b00100001,
0b00010011,
0b00001001,
0b00001000,
0b01100011,
0b00000000,
0b00000001,
0b11111111 // off
};
uint8_t digits[3];
void initADC()
{
ADMUX=(1<<REFS1)|(1<<REFS0);
ADCSRA=(1<<ADEN)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0);
}
uint16_t ReadADC(uint8_t ch)
{
//Select ADC Channel ch must be 0-7
ch=ch&0b00000111;
ADMUX|=ch;
//Start Single conversion
ADCSRA|=(1<<ADSC);
//Wait for conversion to complete
while(!(ADCSRA & (1<<ADIF)));
//Clear ADIF by writing one to it
ADCSRA|=(1<<ADIF);
return(ADC);
}
int main()
{
DDRD = 0xFF;
PORTD = 0xFF;
DDRB = 0b00000001;
PORTB = 1;
initADC();
uint16_t adc_value;
uint16_t res;
while(1)
{
adc_value = 0;
for (int i = 0; i < 250; i++)
{
adc_value += ReadADC(0);
}
adc_value=(adc_value/25)/4;
res = adc_value;
for(int j = 2; j >= 0; j--) {
digits[j] = res%10;
res /= 10;
}
uint8_t dig = digits[0];
PORTD = numbers[dig];
_delay_ms(DELAY_IN_MS);
// if following is uncommented there blinks digit two correctly
// if commented there is unblinking digit 1
PORTD = numbers[10]; // display off
}
return 0;
}
The problem was induction.
My circuit had many wires in non-soldering-field. When the display was on, there was a lot of induction going on changing resulting voltage on ADC input/LM35 output.
There is more than one solution.
1) Software: I moved ADC conversion into the interruption function. It turns of the displays, converts value from lm35 and displays digit on proper display. It happens so fast that the eye cant perceive it.
I prefer this one for now, because it makes my circuit simpler.
2) Hardware: adding L/C or R/C filter to adc pin should resolve the issue.
Full code for 1)
#ifndef F_CPU
#define F_CPU 1000000UL
#endif // F_CPU
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#define DELAY_IN_MS 5000 /* ms */
#define NUM_OF_MEASUREMENTS 100
#define NUM_DISPLAYS 3
int numbers[] = {
0b10000001,
0b10011111,
0b10100100,
0b10010100,
0b10011010,
0b11010000,
0b11000000,
0b10011101,
0b10000000,
0b10010000,
0b11111111 // off
};
int display = 0;
uint8_t digits[NUM_DISPLAYS];
volatile uint16_t adc_values[NUM_OF_MEASUREMENTS];
int adc_read_cycle_index = 0;
uint32_t res;
void initADC()
{
ADMUX=(1<<REFS1)|(1<<REFS0);
ADCSRA=(1<<ADEN)|(1<<ADPS2);
}
uint16_t ReadADC(uint8_t ch)
{
//Select ADC Channel ch must be 0-7
ch=ch&0b00000111;
ADMUX|=ch;
//Start Single conversion
ADCSRA|=(1<<ADSC);
//Wait for conversion to complete
while (ADCSRA & (1<<ADSC));
return(ADC);
}
void readDegrees()
{
adc_values[adc_read_cycle_index] = (ReadADC(0)*10)/4;
if(adc_read_cycle_index + 1 == NUM_OF_MEASUREMENTS) {
adc_read_cycle_index = 0;
} else {
adc_read_cycle_index++;
}
}
void fetchTemperatureDigits() {
res = 0;
for(int i = 0; i < NUM_OF_MEASUREMENTS; i++) {
res += adc_values[i];
}
res /= NUM_OF_MEASUREMENTS;
for(int j = 2; j >= 0; j--) {
digits[j] = res%10;
res = res / 10;
}
}
void initTimer0()
{
// Prescaler = FCPU/64
TCCR0|=(1<<CS01);//|(1<<CS00);
//Enable Overflow Interrupt Enable
TIMSK|=(1<<TOIE0);
//Initialize Counter
TCNT0=0;
}
ISR(TIMER0_OVF_vect)
{
// turn off displays
PORTD = numbers[10];
// read ADC and convert to degrees
readDegrees();
// turn on proper anode
PORTB &= 0b11111000;
PORTB |= (1<<display);
// show digit
PORTD = numbers[digits[display]];
// show decimal point for second display (21.5 - second display shows "1.")
if(display == 1) {
PORTD &= 0b01111111;
}
// next display for next interruption
display++;
if(display == NUM_DISPLAYS) {
display = 0;
}
}
int main()
{
initADC();
for(int i = 0; i < NUM_OF_MEASUREMENTS; i++) {
readDegrees();
}
DDRD = 0xFF;
PORTD = 0;
DDRB |= 0b00000111;
PORTB |= 1;
initTimer0();
sei();
while(1) {
fetchTemperatureDigits();
_delay_ms(DELAY_IN_MS);
}
return 0;
}
Related
I am new to programming in IDE. I am using built-in timer of arduino.I am using TDR method to capture reflection from fault location in cable and for that I am using timer.Timer should start as soon as output is send and stop at reflection. I have a reference code for it but I dont able to understand it, so if anyone know about it , it would be great.
void setup()
{
pinMode(stepPin, OUTPUT);
pinMode(refPin, OUTPUT);
pinMode(shutdownPin, OUTPUT);
TCCR1A = 0;
TCCR1B = (1 << ICNC1); // input capture noise canceller enabled, capture on falling edge
TIMSK1 = 0; // timer 1 interrupts disabled
ACSR = 0; // input capture from ICP1 pin
TCCR2B = (1 << CS20); // change timer 2 PWM frequency to 31.25kHz because we're using pin 11 as a DAC
Serial.begin(19200);
}
struct Step
{
unsigned int time;
unsigned int amplitude;
};
// Take a single measurement, using either a positive or negative edge from the comparator.
// The comparator reference voltage must have been set up and allowed to stablise before calling this.
unsigned int takeMeasurement(bool posEdge)
{
byte reg1b = (posEdge) ? 0 : (1 << ICES1); // input capture noise canceller csdisabled, set up input capture polarity, stop timer
reg1b |= (1 << CS10);
TCCR1B = reg1b;
TCNT1H = 0;
TCNT1L = 0; // clear timer
unsigned int capture = 0;
unsigned long start = micros(); // get the time
cli();
TCNT1H = 0;
TCNT1L = 0; // clear timer
TIFR1 = (1 << ICF1); // clear timer 1 input capture bit
PORTD |= (1 << 4); // set output high
sei();
do
{
if ((TIFR1 & (1 << ICF1)) && capture == 0)
{
byte temp = ICR1L;
capture = (ICR1H << 8) | temp;
}
} while (micros() - start < 100);
PORTD &= ~(1 << 4); // set output low
return capture;
}
size_t findSteps(bool positive, struct Step *results, size_t maxResults)
{
byte amplitude = (positive) ? 5 : 250;
analogWrite(refPin, amplitude);
delay(100); // wait 100ms for the output to stabilise
unsigned int lastReading = 0;
size_t numResults = 0;
unsigned int stepSize = 0; // 0 means not in a step
#ifdef DEBUG
Serial.print((positive) ? "pos " : "neg ");
#endif
for (int i = 0; i < 50; ++i)
{
analogWrite(refPin, amplitude);
delay(10);
unsigned int currentReading = takeMeasurement(positive);
unsigned int currentDiff = currentReading - lastReading; // diff since start of possible step
if (stepSize == 0)
{
// Not currently in a step
if (i != 0 && currentReading != 0 && currentDiff == 0)
{
// Found the start of a possible step
++stepSize;
}
lastReading = currentReading;
}
else
{
if (currentDiff > 2 || i + 1 == 50)
{
// Step has endeed, so record it if it is big enough
if (stepSize >= 2)
{
results->time = lastReading;
results->amplitude = amplitude - 5;
++results;
++numResults;
if (numResults == maxResults) break;
}
stepSize = 0;
lastReading = currentReading;
}
else if (currentDiff == 0)
{
++stepSize;
}
}
#ifdef DEBUG
if (i != 0) Serial.write(',');
Serial.print(currentReading);
#endif
if (positive)
{
amplitude += 5;
}
else
{
amplitude -= 5;
}
}
#ifdef DEBUG
Serial.println();
#endif
return numResults;
}
When selecting the "Build Main Project" and attempting to compile my project, the compiler keeps bringing up these error messages:
Source.c:64:8: error: 'RB6' undeclared (first use in this function)
I believe it has something to do with my #define lines of code, but I'm not certain:
// Include Commands
#include "xc.h"
#include "lcd.h"
#include <stdio.h>
#include <stdlib.h>
#include "pragma.h"
#include <stdbool.h>
// Define Commands
#define LCD_RS RB7
#define LCD_D0 RB15
#define LCD_D1 RB14
#define LCD_D2 RB13
#define ULTRAECHO RA4
#define ULTRATRIG RB5
#define PIR RB6
#define PIRII RB7
#define MOTOR RB4
#define MOTORII RB12
#define XTAL_FREQ 8000000
void setup() {
// A-Type Registers
TRISA = 0;
// 0 - 5
PORTA = 0;
// B-Type Registers
TRISB = 0;
// 0 - 15
PORTB = 0;
LCD_Cmd(LCD_CLEAR);
__delay_ms(50);
LCD_Begin();
}
void loop() {
int value;
value = 0;
__delay_ms(300);
PORTBbits.RB6 = 1;
PORTBbits.RB7 = 1;
if (PIR == 1 || PIRII == 1) { // Checks both PIR Sensors
PORTBbits.RB8 = 1; // Activates LCD Screen
PORTBbits.RB15 = 1;
PORTBbits.RB14 = 1;
PORTBbits.RB13 = 1;
PORTAbits.RA4 = 1; // Activates ULTRASONIC
PORTBbits.RB5 = 1;
LCD_Cmd(LCD_CLEAR);
(value = value + 1);
}
else {
PORTBbits.RB8 = 0; // No Life Detected
PORTBbits.RB15 = 0;
PORTBbits.RB14 = 0;
PORTBbits.RB13 = 0;
(value = value);
}
{
LCD_Goto(1, 1);
LCD_Print(value);
goto __delay_ms(300);
}
{
if (PORTAbits.RA4 = 1 || PORTBbits.RB5 = 1) {
__bit wait_sensor(); // Activates Timer
uint16_t i = 0;
TMR1 = 0; // Resets Timer
TMR1 = 1;
while (!ULTRAECHO && (i < 1000)) {
i = (TMR1 << 8) | TMR1;
if (i >= 1000)
return 0;
else {
return 1;
}
}
}
__bit get_distance(uint16_t *ticks);
{
uint16_t *ticks = 0;
TMR1 = 0;
while (ULTRAECHO && ('uint16_t *ticks' < 23200))
uint16_t *ticks = (TMR1 << 8) | TMR1; // Read Timer Value
TMR1 = 0;
if (uint16_t *ticks >= 23200)
return 1;
else {
return 0;
}
}
{
OSCCON = 0x70; // Sets Timer and Oscillator Value
T1CON = 0x10;
TMR1 = 0;
__delay_ms(500);
ULTRATRIG = 0; // Toggle Pin to LOW
__delay_us(2);
ULTRATRIG = 1; // Generate 10us Pulse
__delay_us(10);
ULTRATRIG = 0;
if (ULTRAECHO = 1) // Read Pulse from ULTRAECHO
uint16_t distance;
if (get_distance()) { // Distance greater than 400cm
LCD_Goto(2, 1);
LCD_Print(" No Proximity ");
MOTORII = 0;
MOTOR = 0;
}
else {
uint16_t distance = uint16_t distance / 58; // Calculates Distance
LCD_Goto(2, 1);
LCD_Print(distance, " cm ");
MOTORII = 1;
MOTOR = 1;
}
uint16_t distance = uint16_t distance / 58;
if (uint16_t distance <= 20)
MOTORII = 0;
MOTOR = 0;
__delay_ms(500);
goto void setup();
}
}
}
Perhaps the placement of my "define" commands are incorrect? Or is there some sort of line of code I'm forgetting? I feel like I'm overthinking this.
Yes, there are issues with your #define directives. They are not defined as they ought to be.
In this block of code:
// Define Commands
#define LCD_RS RB7
#define LCD_D0 RB15
#define LCD_D1 RB14
#define LCD_D2 RB13
#define ULTRAECHO RA4
#define ULTRATRIG RB5
#define PIR RB6
#define PIRII RB7
#define MOTOR RB4
#define MOTORII RB12
Define those macros as:
#define LCD_RS PORTBbits.RB7 //Check if it is RB7 or RB8, as somwhere it is RB8
#define LCD_D0 PORTBbits.RB15
#define LCD_D1 PORTBbits.RB14
#define LCD_D2 PORTBbits.RB13
#define ULTRAECHO PORTAbits.RA4
#define ULTRATRIG PORTBbits.RB5
#define PIR PORTBbits.RB6
#define PIRII PORTBbits.RB7
#define MOTOR PORTBbits.RB4
#define MOTORII PORTBbits.RB12
And use them for example as:
...
PIR = 1;
PIRII = 1;
if (PIR == 1 || PIRII == 1) { // Checks both PIR Sensors
LCD_RS = 1; // Activates LCD Screen
LCD_D0 = 1;
LCD_D1 = 1;
LCD_D2 = 1;
...
Apart from those issues, I think your Input and Output configuring registers TRISA and TRISB are not properly configured.
// A-Type Registers
TRISA = 0;
// 0 - 5
PORTA = 0;
// B-Type Registers
TRISB = 0;
// 0 - 15
PORTB = 0;
In the controller header there is a define like:
#define _RB7 PORTBbits.RB7
so you could also use something like:
#define LCD_RS _RB7
I am making a game where you need to repeat the sequence of LEDs that light up. This sequence is set by two LEDs. To repeat the sequence, I use the joystick.
I had an idea to make two bool arrays where True will indicate the left LED, and False will indicate the right LED. The first array must contain a random sequence(True/False) that needs to be repeated. When I push to one or the other side of the joystick, I want to write to the second array, respectively, True / False and all this time compare them.
This is what I have at the moment. (AT90USB647)
#define F_CPU 2000000UL
#include <avr/io.h>
#include <stdbool.h>
int main(void) {
MCUCR |= 0x80;
MCUCR |= 0x80;
DDRA = 0xFF;
PORTF = 0x20;
bool seq2[100];
while(1)
{
uint8_t x = PINF;
if(!(x & 0x20)) {
PORTA = 0x80;
}
else if(!(x & 0x08)) {
PORTA = 0x01;
}
else {
PORTA = 0x00;
}
}
}
The main question is how do I write True or False to an array when I push the joystick?
A basic approach could be:
#define F_CPU 2000000UL
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
volatile unsigned int counter;
static unsigned char pattern_position;
static unsigned char array_position;
static unsigned char pattern[] = {
0b01010101,
0b11010101,
0b10010101
};
ISR(TIMER0_COMPA_vect)
{
counter++;
}
int main(void)
{
MCUCR |= 0x80;
DDRA = 0xFF;
PORTF = 0x20;
// Timer initialization
// Mode: CTC
// Prescaler: 1024
TCCR0A = (1<<WGM01);
TCCR0B = (1<<CS02) | (1<<CS00);
// Calculate a correct time
//
// we want 1 ms -> f_TIMER0 = 1/T = 1/(1 * 10^-3)s = 1 kHz
//
// f_CPU f_CPU 20 MHz
// f_TIMER0 = ------------- -> OCR0A = ---------------- = ------------- = ~ 20 (It is not exactly 1ms but it is ok)
// k_H * OCR0A k_H * f_TIMER0 256 * 1 kHz
//
OCR0A = 20;
TIMSK0 = (1<<OCF0A); // Enable Timer0 Overflow Compare Match interrupt
// Show the sequence that the user should input
for (unsigned char i=0; i < sizeof(pattern)/sizeof(&pattern[0]); i++)
{
for (unsigned char j=0; j < 8; j +=2)
{
// There is possible a signal missing to show the user that the next pattern occurs!
PORTA = ((pattern[i]>>(j+1))<<PINA7) | ((pattern[i]>>j)<<PINA0);
// That the user can see the patterns a delay is necessary!
_delay_ms(1000);
}
}
// Signalize that the game starts
for (unsigned char i=0; i <8; i++)
{
PORTA ^= 0x81;
_delay_ms(1000);
}
TCNT0 = 0x00;
sei();
while(1)
{
// There is possible a signal missing to trigger next pattern input to the user!!!
if(!(PINF & (1<<PINF5)))
{
PORTA |= 0x80;
}
if(!(PINF & (1<<PINF3)))
{
PORTA |= 0x01;
}
// Time is 4 seconds to match the correct pattern
if(counter >= 4000)
{
if(!((pattern[pattern_position] & (1<<array_position)) == (0x01 & PORTA)))
{
// Wrong input end of game
}
array_position++;
if(!((pattern[pattern_position] & (1<<array_position)) == (0x01 & (PORTA>>8))))
{
// Wrong input end of game
}
array_position++;
if(array_position >= 8)
{
array_position = 0;
pattern_position++;
}
if(pattern_position >= (sizeof(pattern)/sizeof(&pattern[0])))
{
// End of game reached winning!
}
counter = 0x00;
PORTA = 0x00;
TCNT0 = 0x00;
}
}
}
I´m not sure if you are exactly trying this to do and i also can not test the code on your target platform but maybe this is a rudimental approach to solve your problem...
I am currently working on a code involving the MPLAB XC8 Compiler, PIC18F452 with a Multiplexed Seven Segment Display. I want to use two pushbuttons connected to pins RB2 and RB3 of PORTB of the PIC18F452 to increment and decrement a variable "count" and display this number from 0 to 99 on this display. Schematic and code is show below.
This code relatively functions as it is, and I do not believe the schematic is to blame for the issues I am seeing, nor is the byte array not correct as I am able to see each number when using the array with a 1 segment display.
The issue arrises when trying to use this multiplexing scheme shown in the below figure. I can successfully display two numbers on the seven segment displays, but there are strange anomalies present when executing this code. For one, I seem to not be able to display the number 1, 4 and occasionally 7 on either display, but when this digit does not show the display is blank, and when the button is again pushed the next number is shown as expected.
for example:
The display shows the numbers as follows for number sequences:
9... 10... 11... 12 13... 14... ect...
or
34.... 35... 36... 37....
Not sure where the issues lies, and debugging is not going well... any help would be appreciated.
Schematic for Multiplexed 7 Segment Display
#define _XTAL_FREQ 10000000
#include <xc.h>
#include <stdlib.h>
#define Digit1 PORTBbits.RB1 //variable to sink current to PNP base
#define Digit2 PORTBbits.RB2 //variable to sink current to PNP base
#define Switch1 PORTBbits.RB4 //switch decrement variable
#define Switch2 PORTBbits.RB3 //switch increment variable
#define Pressed1 1 //pressed is high
#define Pressed2 1 //pressed is high
void initialize();
void segment1 (void);
void segment2 (void);
void buttonPress(void);
void delay_ms(unsigned int);
void sendPattern1(unsigned char pattern);
void sendPattern2(unsigned char pattern3);
unsigned char rotateLeft(unsigned char pattern, int no);
unsigned char MSD, LSD, count=0;
Main code
void main(void){
initialize();
Digit1 = 0;
Digit2 = 0;
while(1){
buttonPress();
MSD = count/10 ;
segment1();
Digit2 = 1;
delay_ms(10); // Delay for 10 ms
Digit2 = 0;
LSD = count%10;
segment2();
Digit1 = 1;
delay_ms(10); // Delay for 10 ms
Digit1 = 0;
}
return;
}
Functions to index Most Significant Digit and Least Significant Digit from array to be sent to the ports to sink current low for common annode display.
void segment1(void){
unsigned char segArrayC[]={0b11000000,0b11111001,0b00100100,
0b00110000,0b00011001,0b00010010,
0b00000010,0b11111000,0b00000000,0b00011000};
unsigned char pattern;
pattern = segArrayC[MSD];
sendPattern1(pattern);
return;
}
void segment2(void){
unsigned char segArrayD[]= {0b11000000,0b11111001,0b00100100,
0b00110000,0b00011001,0b00010010,0b00000010,
0b11111000,0b00000000,0b00011000};
unsigned char pattern3;
pattern3 = segArrayD[LSD];
sendPattern2(pattern3);
return;
}
Button Press Code
void buttonPress(void){
if (Switch1 == Pressed1) {
++count;
delay_ms(100);
}
if (Switch2 == Pressed2) {
--count;
delay_ms(100);
}
if(count>=99||count<0)
{
count=0;
delay_ms(100);
}
return;
}
Function to rotate bytes in array two places to left to be displayed on PORTs
/** Rotate pattern to the left 'no' number of bits
*/
unsigned char rotateLeft(unsigned char pattern, int no) {
return (((pattern << no) & 0xFF) | (pattern >> (8-no)));
}
Functions to output indexed array char to PORTC and PORTB pins
void sendPattern1(unsigned char pattern) {
// Send pattern to appropriate port pins
unsigned char pattern2;
PORTC = pattern;
pattern2=rotateLeft(pattern, 2);
PORTB = pattern2;
return;
}
void sendPattern2(unsigned char pattern3) {
unsigned char pattern4;
PORTC = pattern3;
pattern4=rotateLeft(pattern3, 2);
PORTB = pattern4;
return;
}
Delay Function
void delay_ms(unsigned int n){
while (--n) _delay(2500);
}
Initialize pins to be used (0 output, 1 input)
void initialize() {
TRISC = 0;
TRISBbits.TRISB0 = 0;
TRISBbits.TRISB1 = 0;
TRISBbits.TRISB2 = 0;
TRISBbits.TRISB4 = 1;
TRISBbits.TRISB3 = 1;
PORTC = 0x00;
PORTB = 0x00;
}
In sendPattern() you write a rotated bit pattern to PORTB.
This interferes with the setting the common anode control. So you see both digits only, if both right hand segments are turned on. According your schematic you should write a 0 to turn on the common anode. Try this:
void main()
{
static const unsigned char segArray[]=
{ 0b11000000, 0b11111001, 0b00100100, 0b00110000, 0b00011001,
0b00010010, 0b00000010, 0b11111000, 0b00000000, 0b00011000
};
TRISC = 0; //PortC all OUTPUT
PORTC = 0xFF; //PortC all HIGH = IDLE = LED_OFF
TRISBbits.TRISB0 = 0; //Output unused
TRISBbits.TRISB1 = 0; //Output Digit1
TRISBbits.TRISB2 = 0; //Output Digit2
TRISBbits.TRISB4 = 1; //Input: Switch PLUS
TRISBbits.TRISB3 = 1; //Input: Switch MINUS
PORTB = 0x00;
unsigned char count=0;
for(;;)
{
//Handle buttons
if (Switch1 && count<99)
{
++count;
delay_ms(100);
}
if (Switch2 && count > 0)
{
--count;
delay_ms(100);
}
//Write high digit
PORTC = segArray[count/10];
Digit2 = 0;
delay_ms(10); // Delay for 10 ms
Digit2 = 1;
//Write low digit
PORTC = segArray[count%10];
Digit1 = 0;
delay_ms(10); // Delay for 10 ms
Digit1 = 1;
}
}
I am using Atmel Studio 6.1 and this is the code that I use, beside this i also got another code called "ledstrip.h". Which basically is an 1 dimensional array.
This is something for my study.
I am trying to send 12 bytes through a 'ledstrip'
code:
#define SPI_SS_bm PIN4_bm
#define SPI_MOSI_bm PIN5_bm
#define SPI_MISO_bm PIN6_bm
#define SPI_SCK_bm PIN7_bm
#define MIN_VALUE 0.4
#define F_CPU 32000000UL
#define P 128
#define FOO 0
#include <avr/io.h>
#include <util/delay.h>
#include <avr/pgmspace.h>
#include <avr/interrupt.h>
#include "ledstrip.h"
void spi_init(void);
uint8_t spi_transfer(uint8_t data);
const uint8_t *ptr = image;
uint8_t num[12];
int line;
int g;
int data;
int i;
void row (const uint8_t *j)
{
uint32_t row2 = 0;
for(g = 0; g < 4; g++)
{
for(int i = 0; i < 8; i++)
{
row2 = (row2 << 3) | pgm_read_byte(j);
j++;
}
num[3*g] = (uint8_t) (row2 >> 16); //put bytes in the right order
num[3*g+1] = (uint8_t) (row2 >> 8);
num[3*g+2] = (uint8_t) (row2);
}
}
void spi_initialisation(void)
{
PORTC.DIRSET = SPI_SCK_bm|SPI_MOSI_bm|SPI_SS_bm;
PORTC.DIRCLR = SPI_MISO_bm;
SPIC.CTRL = (!SPI_CLK2X_bm) | // no double clock speed
SPI_ENABLE_bm | // SPI enable
!SPI_DORD_bm | // data order, MSB first
SPI_MASTER_bm | // master
SPI_MODE_0_gc | // mode 0
SPI_PRESCALER_DIV4_gc; // Presc. 4 (#2 MHz,500kHz)
}
void spi_init(void)
{
PORTC.DIRSET = PIN7_bm|PIN5_bm|PIN4_bm; // 7: MOSI 5: SCK
PORTC.OUTCLR = PIN4_bm; // 4: latch enable
PORTD.DIRSET |= PIN3_bm|PIN1_bm; // 3: MOSI 1: SCK
USARTC1.BAUDCTRLA = 0; // baud rate FCPU/2
USARTC1.BAUDCTRLB = 0; //
USARTC1.CTRLC = USART_CMODE_MSPI_gc; // SPI mode
USARTC1.CTRLA = 0; // no interrupts
USARTC1.CTRLB = USART_TXEN_bm; // enable transmit
USARTD0.BAUDCTRLA = 0; // baud rate FCPU/2
USARTD0.BAUDCTRLB = 0; //
USARTD0.CTRLC = USART_CMODE_MSPI_gc; // SPI mode
USARTD0.CTRLA = 0; // no interrupts
USARTD0.CTRLB = USART_TXEN_bm; // enable transmit
}
void init_timer_phi(void)
{
TCE0.CTRLA = TC_CLKSEL_DIV8_gc; // prescaling P
TCE0.CTRLB = TC_WGMODE_NORMAL_gc; // normal mode
TCE0.INTCTRLA = TC_OVFINTLVL_LO_gc;
TCE0.PER = 1440; // t = PER*FCPU/P =
// FCPU*P/32M = 1 us
}
ISR (TCE0_OVF_vect)
{
ptr = ptr +32;
if(ptr >= image + 32 * 360)
{
ptr = image;
} // send bytes to ledstrip
}
void init_inputcapture(void)
{
PORTC.PIN2CTRL = PORT_ISC_FALLING_gc;
PORTC.DIRCLR = PIN2_bm; // Pin 2 is input
EVSYS.CH0MUX = EVSYS_CHMUX_PORTC_PIN2_gc; // Select PC2 as input
// to event channel 0
TCC0.CTRLD = TC_EVACT_CAPT_gc | // Event capture
TC_EVSEL_CH0_gc; // for Channel 0
TCC0.CTRLB = TC0_CCAEN_bm; // Enable Inp. Capt. Ch. A
TCC0.CTRLA = TC_CLKSEL_DIV256_gc; // Start timer
TCC0.INTCTRLB = TC_CCAINTLVL_LO_gc; // Set Interr. level Ch. A
TCC0.PER = 0xFFFF;
}
ISR(TCC0_CCA_vect)
{
uint16_t v;
v = TCC0.CCA;
if (v > MIN_VALUE)
{ // skip if measured value is too small
line = 0; // reset image
TCE0.PER = (v * 360/(F_CPU / P)); // calculate periode
TCC0.CTRLFSET = TC_CMD_RESTART_gc; // restart input capture
}
}
void spi_write_byte(uint8_t data)
{
PORTC.OUTCLR = SPI_SS_bm;
spi_transfer(data);
PORTC.OUTSET = SPI_SS_bm;
}
uint8_t spi_read_byte(void)
{
uint8_t data;
PORTC.OUTCLR = SPI_SS_bm;
data = spi_transfer (FOO);
PORTC.OUTSET = SPI_SS_bm;
return data;
}
int main(void)
{
uint8_t i = 0;
spi_init();
PORTC.DIRSET = PIN0_bm;
PMIC.CTRL |= PMIC_LOLVLEN_bm;
sei();
PORTC.DIRSET = PIN4_bm | PIN5_bm | PIN6_bm | PIN7_bm;
while(1)
{
SPIC.DATA = i; // send i
while( ! (SPIC.STATUS & (SPI_IF_bm)) ); // wait until send
PORTC.OUTSET = PIN0_bm; // store
PORTC.OUTCLR = PIN0_bm;
_delay_ms(100);
i++;
}
}
Okay, so I got this code with no errors and warnings.
But when I run the program on my microcontroller ATXMega128A4U, I don't get the intended output.
There is a possibility that I didn't connect the pins of my 'ledstrip' in the right way with the pins of the microcontroller.
But if we consider that I did it like I intended to, the problem should be in the code.
The intended signal is 12 bytes long and with that I can turn RGB LED's on or off.
The RGB LED's are put together in a so called 'ledstrip'
Now what I'm getting is that some of the RGB LED's turn on and are Red Green or Blue.
What i should be getting is something like a chasing RGB LED row.
So you would see the LED's turn on or off at a certain frequency.