I have tried to define a 2 dimension array in c language and initialize it with variables of float types but I have got this error:
"must be constant expression"
here is my code:
/*******************************************************
This program was created by the
CodeWizardAVR V3.12 Advanced
Automatic Program Generator
© Copyright 1998-2014 Pavel Haiduc, HP InfoTech s.r.l.
http://www.hpinfotech.com
Project :
Version :
Date : 1/30/2017
Author :
Company :
Comments:
Chip type : ATmega8A
Program type : Application
AVR Core Clock frequency: 8.000000 MHz
Memory model : Small
External RAM size : 0
Data Stack size : 256
*******************************************************/
#include <mega8.h>
#include <stdio.h>
#include <delay.h>
#include <alcd.h>
#define A Hall_1
#define B Hall_2
#define C Hall_3
//...........................................................................................
// Declare your global variables here
float Hall_1 ,Hall_2 ,Hall_3 ;
int count=0;
//----------------------------------------------------------------------------------------------------
// Timer 0 overflow interrupt service routine
interrupt [TIM1_OVF] void timer1_ovf_isr(void)
{
count++;
}
//----------------------------------------------------------------------------------------------
// ADC interrupt service routine
interrupt [ADC_INT] void adc_isr(void)
{
}
//-----------------------------------------------------------------------------------------------
float adc_read(unsigned char);
float maxf(float , float , float);
float minf(float , float , float);
void commutate(unsigned char*);
//-----------------------------------------------------------------------------------------------
void main(void)
{
// Declare your local variables here
float comt_sequence[6][2]= {{B,A},{B,C},{A,C},{A,B},{C,B},{C,A}};
// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: 8000.000 kHz
TCCR1B=(0<<CS02) | (0<<CS01) | (0<<CS00);
TCNT1=0x00;
// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=(0<<OCIE2) | (0<<TOIE2) | (0<<TICIE1) | (0<<OCIE1A) | (0<<OCIE1B) | (0<<TOIE1) | (0<<TOIE0);
// External Interrupt(s) initialization
// INT0: Off
// INT1: Off
MCUCR=(0<<ISC11) | (0<<ISC10) | (0<<ISC01) | (0<<ISC00);
// ADC initialization
// ADC Clock frequency: 250.000 kHz
// ADC Voltage Reference: Int., cap. on AREF
// Only the 8 most significant bits of
// the AD conversion result are used
ADMUX= (1<<REFS1) | (1<<REFS0) | (1<<ADLAR) ;
ADCSRA=(1<<ADEN) | (0<<ADSC) | (0<<ADFR) | (0<<ADIF) | (0<<ADIE) | (1<<ADPS2) | (0<<ADPS1) | (1<<ADPS0);
SFIOR=(0<<ACME);
// Alphanumeric LCD initialization
// Connections are specified in the
// Project|Configure|C Compiler|Libraries|Alphanumeric LCD menu:
// RS - PORTD Bit 0
// RD - PORTD Bit 1
// EN - PORTD Bit 2
// D4 - PORTD Bit 4
// D5 - PORTB Bit 6
// D6 - PORTB Bit 7
// D7 - PORTD Bit 5
// Characters/line: 16
lcd_init(40);
// Global enable interrupts
#asm("sei")
lcd_putsf("start");
delay_ms(500);
lcd_clear();
while (1)
{
unsigned char buffer[18] , s=0;
float m,n=0 , max_min[2];
TCCR1B=1; //start counting cycles
Hall_1 = adc_read(5);
Hall_2 = adc_read(4);
Hall_3 = adc_read(3);
m=maxf(Hall_1,Hall_2,Hall_3);
/*if(m == Hall_1)
lcd_putsf("Max= A ");
else if(m == Hall_2)
lcd_putsf("Max= B ");
else if(m == Hall_3)
lcd_putsf("Max= C ");
else
lcd_putsf("Error"); */
n=minf(Hall_1,Hall_2,Hall_3);
/*if(n == Hall_1)
lcd_putsf("Min= A");
else if(n == Hall_2)
lcd_putsf("Min= B");
else if(n == Hall_3)
lcd_putsf("Min= C");
else
lcd_putsf("Error");*/
max_min[0] = m;
max_min[1] = n;
s=count;
sprintf(buffer,"%5.4f %5.4f %d",max_min[0],max_min[1] ,TCNT1);
lcd_puts(buffer);
delay_ms(1000);
lcd_clear();
}
}
///////////////////////////////////////////////
float adc_read(unsigned char ch)
{
unsigned char lcd_buff[18];
float adc_data;
// select the corresponding channel 0~7
// ANDing with ’7' will always keep the value
// of ‘ch’ between 0 and 5 ""ATmega8 has 6 ADC channel 0-5""
ch &= 0b00000111; // AND operation with 5
ADMUX = (ADMUX & 0xF8)|ch; // clears the bottom 3 bits before ORing
// start single convertion
// write ’1' to ADSC
ADCSRA |= (1<<ADSC);
// Wait for the AD conversion to complete
while ((ADCSRA & 0x10)==0);
ADCSRA|=0x10;
// Read the 8 most significant bits
// of the AD conversion result
adc_data=(ADCH * 2.56)/255;
//sprintf(lcd_buff," %5.3f ",adc_data);
//lcd_puts(lcd_buff);
//delay_ms(500);
return adc_data;
}
//------------------------------------------------------------------------------------------------
float maxf(float a , float b , float c) {
float m;
m = (a>b)?a:b;
m = (m>c)?m:c;
return m;
}
float minf(float a , float b , float c) {
float m;
m = (a<b)?a:b;
m = (m<c)?m:c;
return m;
}
//--------------------------------------------------------------------------------------
void commutate(unsigned char *max_min){
unsigned char x=0, i=0;
//unsigned char comt_pattern[6][2] = {(
for (i=0; i<6 ;i++)
if((max_min[0] == comt_sequence[i][0]) && (max_min[1] == comt_sequence[i][1])) x=i;
switch(x){
case 0:
break;
case 1:
break;
case 2:
break;
case 3:
break;
case 4:
break;
case 5:
break;
}
}
i add my whole code also i mention that Hall variables holds an ADC reading from a sensor and its values changes periodically what is my fault?
please help
You may not initialize arrays in C with static storage duration with non-constant initializers.
From the C Standard (6.7.9 Initialization)
4 All the expressions in an initializer for an object that has static
or thread storage duration shall be constant expressions or string
literals.
It seems your array is declared outside any function. If it is possible declare it in a function for example in main.
When creating an array like that, its size must be constant, because C doesn't allow non-constant values for the size of an array.
C99 standard section 6.7.8 (Initialization), point 4:
All the expressions in an initializer for an object that has static
storage duration shall be constant expressions or string literals.
I did changes your code. try it.
#include <stdio.h>
#define Hall_1 10
#define Hall_2 20
#define Hall_3 30
int main()
{
float A,B,C;
A = Hall_1;
B = Hall_2;
C = Hall_3;
float commutate_sequence[6][2]= {{B,A},{B,C},{A,C},{A,B},{C,B},{C,A}};
return 0;
}
I changed code as follow and it works now:
#define A Hall_1
#define B Hall_2
#define C Hall_3
void commutate(unsigned char max_min)
{ unsigned char X=0, i=0;
float comt_sequence[6][2]= { (&Hall_2,&Hall_1) , (&Hall_2,&Hall_3),(Hall_1,&Hall_3) , (&Hall_1,&Hall_2), &Hall_3,&Hall_2) , (&Hall_3,&Hall_1) };
for (i=0; i<6 ;i++)
{ if( (max_min[0] == (*comt_sequence[i][0])) && (max_min[1] == (*comt_sequence[i][1]))) X=i;}
Related
I'm new to embedded systems and C programming. I am currently trying to program a PCB using an STM32 microcontroller to control an array of 8 fans upon receipt of a single commenad. i.e 00001011 will switch on fans 5, 7 and 8. There are a total of 256 possible combinations and it wouldn't be very efficient to program each individual one.
I am thinking of using an array to achieve this using something like;
fan_array[8] = {fan1, fan2, fan3, fan4, fan5, fan6, fan7, fan8};
printf ("Input fan state"); // user would input binary number as shown above
scanf (%d, fan_array);
Would this set the GPIO pins controlling each fan high or low according to the binary values input into the array?
If you think about it, there are 256 possible combinations, but you're only interested in 8 fans, so all that you need to check is 8 bits:
#include <stdio.h>
#define STATE_ON 0x01
#define STATE_OFF 0x00
void enable_relay(unsigned char relay, unsigned char state)
{
/* This is a brute force approach that enables any relay/port combination:
* relay 8: PB2
* relay 7: PB4
* (...)
* relay 1: PA1
*/
switch(relay)
{
case 8:
if(state == STATE_ON)
GPIOB->ODR |= 0x0004;
else
GPIOB->ODR &= ~0x0004;
break;
case 7:
if(state == STATE_ON)
GPIOB->ODR |= 0x0010;
else
GPIOB->ODR &= ~0x0010;
break;
case 1:
if(state == STATE_ON)
GPIOA->ODR |= 0x0002;
else
GPIOA->ODR &= ~0x0002;
break;
}
}
void check_relay(unsigned char fan_map)
{
int i;
unsigned char bit;
unsigned char state;
for(i=0; i < 8; i++) {
bit = (fan_map&(0x01<<i));
state = ((bit != 0)? STATE_ON : STATE_OFF);
enable_relay( (8-i), state);
}
}
int main(void)
{
unsigned char fan_map = 0x0B; /* 0x0B = 00001011 */
check_relay(fan_map);
}
You need the 8-i part as your bit order is in reverse (fan1 as the leftmost bit) with the value order (MSB is the leftmost bit).
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'm trying to run the following code in c on a beaglebone black (microcontroller running Debian).
The code compiles but terminates right when the pwm_init() function is called.
No printf will execute after this line, even the first in the pwm_init() function.
I tried removing pwm_init(), and then wait_for_pwm() will run normally.
This is a code to setup an interrupt timer on the beaglebone in order to communicate with a DAC through SPI.
The code was running and could communicate before this adding.
/*
*Filename: mems.c
*SPI test program to communicate with AD5666 DAC on Micro Mirror Driver board */
#include <stdint.h>
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include "iolib.h"
#include <unistd.h>
#define DELAY_NS 62500 // Timer period in ns
// PRU Interrupt control registers
#define PRU_INTC 0x00020000 // Start of PRU INTC registers TRM 4.3.1.2
#define PRU_INTC_GER ((volatile uint32_t *)(PRU_INTC + 0x10)) // Global Interrupt Enable, TRM 4.5.3.3
#define PRU_INTC_SICR ((volatile uint32_t *)(PRU_INTC + 0x24)) // Interrupt, TRM 4.5.3.6
#define PRU_INTC_GPIR ((volatile uint32_t *)(PRU_INTC + 0x80)) // Interrupt, TRM 4.5.3.11
// PRU ECAP control registers (i.e. PWM used as a timer)
#define ECAP 0x00030000 // ECAP0 offset, TRM 4.3.1.2
// Using APWM mode (TRM 15.3.2.1) to get timer (TRM 15.3.3.5.1)
#define ECAP_TSCTR ((volatile uint32_t *)(ECAP + 0x00)) // 32-bit counter register, TRM 15.3.4.1.1
#define ECAP_APRD ((volatile uint32_t *)(ECAP + 0x10)) // Period shadow, TRM 15.3.4.1.5, aka CAP3
#define ECAP_ECCTL2 ((volatile uint32_t *)(ECAP + 0x2a)) // Control 2, TRM 15.3.4.1.8
#define ECAP_ECEINT ((volatile uint16_t *)(ECAP + 0x2c)) // Enable interrupt, TRM 15.3.4.1.9
#define ECAP_ECCLR ((volatile uint16_t *)(ECAP + 0x30)) // Clear flags, TRM 15.3.4.1.11
// R30 is the GPIO register
// R31 is the interrupt register
#define NUMBER_OF_COEFS 87
int xn[NUMBER_OF_COEFS] = { 0 };
int ynn[NUMBER_OF_COEFS] = { 0 };
int xy[2];
static double coefs[NUMBER_OF_COEFS] = { -0.003874396983162784,-0.0037425007502381417,0.0007168162935488041,-0.0015837981969284466,0.001324731958160302,0.000940030114550933,0.002909179571989647,0.002970492669088027,0.0037475240063036684,0.003135242276391628,0.002431551570668268,0.0007465565198417194,-0.0010918847362976609,-0.0032610680167253635,-0.0050886443383995035,-0.0064219306251743396,-0.0067757336585719885,-0.00603689840577871,-0.004073405037328031,-0.001084864753089533,0.002607744624181485,0.006446336960328277,0.009805149887731802,0.012005211009068262,0.01248315933178856,0.010855477027307714,0.007038206816858291,0.0013011753812607633,-0.005726736257811221,-0.013085733616184817,-0.019608024169477135,-0.024024160014903175,-0.025137566107801428,-0.022018671074884637,-0.01412798218138592,-0.0014477915111131118,0.015482420337480308,0.03556527369143834,0.057256428960766804,0.07871540989639365,0.09799912606296178,0.1132905004893123,0.12311069228747347,0.1265004803246064,0.12311069228747347,0.1132905004893123,0.09799912606296178,0.07871540989639365,0.057256428960766804,0.03556527369143834,0.015482420337480308,-0.0014477915111131118,-0.01412798218138592,-0.022018671074884637,-0.025137566107801428,-0.024024160014903175,-0.019608024169477135,-0.013085733616184817,-0.005726736257811221,0.0013011753812607633,0.007038206816858291,0.010855477027307714,0.01248315933178856,0.012005211009068262,0.009805149887731802,0.006446336960328277,0.002607744624181485,-0.001084864753089533,-0.004073405037328031,-0.00603689840577871,-0.0067757336585719885,-0.0064219306251743396,-0.0050886443383995035,-0.0032610680167253635,-0.0010918847362976609,0.0007465565198417194,0.002431551570668268,0.003135242276391628,0.0037475240063036684,0.002970492669088027,0.002909179571989647,0.000940030114550933,0.001324731958160302,-0.0015837981969284466,0.0007168162935488041,-0.0037425007502381417,-0.003874396983162784};
#define REF_ON 0x01000008 //command to turn on internal VREF
#define X_OFFSET 3
#define Y_OFFSET 0
#define X_DRIVE 1
#define Y_DRIVE 2
#define SIZEMAT 2
float tabx[SIZEMAT] = { -100, 100 };
float taby[SIZEMAT] = { -100, 100 };
// Forward definitions
int convert_spi(int dac_val,int channel); //formats bytes for write function
inline void pwm_init();
inline void wait_for_pwm_timer();
int* fir_filterXY(int x, int y);
int main(int argc, char **argv){
int i, fd, debug=0, loop=0, user_loop=0;
int x_off=-1, y_off=-1;
int x_val=-1, y_val=-1;
int freq = -1;
unsigned int buf = REF_ON;
unsigned int dac_value = 1; // 0 to 65535 value to set dac output
unsigned int spi_bytes = 0; // spi communication bytes to send
char direction = 0; // Direction of triangle wave ramp
fd = open("/dev/spidev1.0", O_RDWR);
if(fd < 0) printf("spi failed to open\n");
iolib_init();
//Set LDAC control pin to output
iolib_setdir(9,15,1);
//Tying LDAC low will update dac channel as soon as it has new data
pin_low(9,15); //sel0
write(fd,&buf,4); //set internal vref on
// User loop
int valx = 0;
int valy = 0;
int* ass;
int assx = 0;
int assy = 0;
int i = 0;
int freqcnt = 0;
int freqi = 0;
if (freq>1000)
{
freq = 1000;
}
if (freq<1)
{
freq = 1;
}
freqcnt = (int)((1000000000/DELAY_NS)/freq - 1);
spi_bytes = convert_spi(32000, X_OFFSET);//format bytes for write function
write(fd, &spi_bytes, 4);
spi_bytes = convert_spi(32000, Y_OFFSET);//format bytes for write function
write(fd, &spi_bytes, 4);
printf("In user loop with movement frequency of:%i\n", freq);
pwm_init();
valx = 32000;
valy = 32000;
assx = 32000;
assy = 32000;
printf("starting\n");
while (1){
wait_for_pwm_timer();
spi_bytes = convert_spi(assx, X_DRIVE);//format bytes for write function
write(fd, &spi_bytes, 4);
spi_bytes = convert_spi(assy, Y_DRIVE);//format bytes for write function
write(fd, &spi_bytes, 4);
freqi++;
if(freqi >= freqcnt){
valx = (int)((tabx[i]+100) * 320);
valy = (int)((taby[i]+100) * 320);
freqi = 0;
i++;
if (i >= SIZEMAT)
i = 0;
}
ass = fir_filterXY(valx, valy);
assx = *(ass);
assy = *(ass+1);
}
return 0;
}
/* Function: convert_spi
*
* Takes a dac value (0-65535) and a dac channel (or all channels) and generates the appropriate 32bits to send to AD5666 via SPI
*
* INPUTS
* dac_val: sets the voltage output with voltage output= 2.5*(dac_val/65535)
* channel: selects which dac channel to update with dac_val. 0=DACA ,1=DACB, 2=DACC, 3=DACD, 16=all
*
* RETURNS
* spi_data: integer value to send via spi using to update channel with new dac value
*/
int convert_spi(int dac_val,int channel){
int spi_data=0;
unsigned int nibble1;
unsigned int nibble2;
unsigned int nibble3;
unsigned int nibble4;
nibble1= dac_val & 0xF000;
nibble2= dac_val & 0x0F00;
nibble3= dac_val & 0x00F0;
nibble4= dac_val & 0x000F;
spi_data |=(nibble1>>4);
spi_data |=(nibble2<<12);
spi_data |=(nibble3<<12);
spi_data |=(nibble4<<28);
spi_data |=(channel<<12);
return spi_data;
}
// Initializes the PWM timer, used to control output transitions.
// Every DELAY_NS nanoseconds, interrupt 15 will fire
inline void pwm_init(){
printf("Intereupt setup");
*PRU_INTC_GER = 1; // Enable global interrupts
printf("1");
*ECAP_APRD = DELAY_NS / 5 - 1; // Set the period in cycles of 5 ns
printf("2");
*ECAP_ECCTL2 = (1<<9) /* APWM */ | (1<<4) /* counting */;
printf("3");
*ECAP_TSCTR = 0; // Clear counter
printf("4");
*ECAP_ECEINT = 0x80; // Enable compare equal interrupt
printf("5");
*ECAP_ECCLR = 0xff; // Clear interrupt flags
printf("done\n");
}
// Wait for the PWM timer to fire.
// see TRM 15.2.4.26x
inline void wait_for_pwm_timer() {
register unsigned int __R31;
while (!(__R31 & (1 << 30))) {} // Wait for timer compare interrupt
*PRU_INTC_SICR = 15; // Clear interrupt
*ECAP_ECCLR = 0xff; // Clear interrupt flags
}
int* fir_filterXY(int x, int y){
int i = 0;
double temp = 0;
for (i = 0; i < NUMBER_OF_COEFS - 1; i++)
{
xn[i] = xn[i + 1]; //xn est au bout
}
xn[NUMBER_OF_COEFS-1] = x;
//multiplier par les coef
for (i = 0; i < NUMBER_OF_COEFS; i++)
{
temp += xn[NUMBER_OF_COEFS - i] * coefs[i];
}
xy[0] = (int)(temp+0.5);
for (i = 0; i < NUMBER_OF_COEFS - 1; i++)
{
ynn[i] = ynn[i + 1];
}
ynn[NUMBER_OF_COEFS-1] = y;
temp = 0;
for (i = 0; i < NUMBER_OF_COEFS; i++)
{
temp += ynn[NUMBER_OF_COEFS - i] * coefs[i];
}
xy[1] = (int)(temp + 0.5);
return xy;
}
A couple of recommendations:
printf() can occasionally lag in its output. To be very sure that nothing is being printed, call fflush(stdout) after the print line. This will flush the stdout buffer-- if nothing is printed after the flush, then the println() really is not being executed.
How is your program terminating? If execution does not continue past the pwm_init() function, that almost certainly means that something bad is happening with the memory locations you are writing to. Double check that your register values are correct and that your program isn't being killed due to invalid memory access.
I am currently trying to make a Random Number Generator using a MSP430 (MSP43 G2553) and then create an algorithm for a Pseudo Random Number Generator. I have a code for these two processes and also a code used to test the programs with LEDs.
For some reason, I encounter some errors that I cannot seem to resolve. I will attach the codes and the errors to get a second opinion on the syntax.
#include <msp430g2553.h>
#include "rand.h"
/**
* Random number generator.
*
* NOTE: This affects Timer A.
*
* Algorithm from TI SLAA338:
* http://www.ti.com/sc/docs/psheets/abstract/apps/slaa338.htm
*
* #return 16 random bits generated from a hardware source.
*/
unsigned int rand(); {
int i, j;
unsigned int result = 0;
/* Save state */
unsigned int TACCTL0_old = TACCTL0;
unsigned int TACTL_old = TACTL;
/* Set up timer */
TACCTL0 = CAP | CM_1 | CCIS_1; // Capture mode, positive edge
TACTL = TASSEL_2 | MC_2; // SMCLK, continuous up
/* Generate bits */
for (i = 0; i < 16; i++) {
unsigned int ones = 0;
for (j = 0; j < 5; j++) {
while (!(CCIFG & TACCTL0)); // Wait for interrupt
TACCTL0 &= ~CCIFG; // Clear interrupt
if (1 & TACCR0) // If LSb set, count it
ones++;
}
result >>= 1; // Save previous bits
if (ones >= 3) // Best out of 5
result |= 0x8000; // Set MSb
}
/* Restore state */
TACCTL0 = TACCTL0_old;
TACTL = TACTL_old;
return result;
}
/**
* Pseudo-random number generator.
*
* Implemented by a 16-bit linear congruential generator.
* NOTE: Only treat the MSB of the return value as random.
*
* #param state Previous state of the generator.
* #return Next state of the generator.
*/
unsigned int prand(unsigned int state) {
return (M * state + I); // Generate the next state of the LCG
}
This is the code for the RNG and PRNG. The list of errors:
Warning[Pa050]: non-native end of line sequence detected (this diagnostic is only issued once) E:\Downloads\msp430-rng-master\rand.h 1
Error[Pe169]: expected a declaration E:\Downloads\msp430-rng-master\rand.c 18
Error[Pe169]: expected a declaration E:\Downloads\msp430-rng-master\rand.c 39
Error[Pe169]: expected a declaration E:\Downloads\msp430-rng-master\rand.c 41
Error[Pe169]: expected a declaration E:\Downloads\msp430-rng-master\rand.c 45
Error[Pe169]: expected a declaration E:\Downloads\msp430-rng-master\rand.c 47
Warning[Pe012]: parsing restarts here after previous syntax error E:\Downloads\msp430-rng-master\rand.c 50
Error[Pe077]: this declaration has no storage class or type specifier E:\Downloads\msp430-rng-master\rand.c 51
Error[Pe147]: declaration is incompatible with "unsigned short volatile TA0CTL # 0x160" (declared at line 527 of "C:\Program Files (x86)\IAR Systems\Embedded E:\Downloads\msp430-rng-master\rand.c 51
Workbench 6.5\430\inc\msp430g2553.h")
Error[Be022]: location address not allowed for initialized variables (writable variables without the __no_init attribute) E:\Downloads\msp430-rng-master\rand.c 51
Error[Pe020]: identifier "TACTL_old" is undefined E:\Downloads\msp430-rng-master\rand.c 51
Error[Pe169]: expected a declaration E:\Downloads\msp430-rng-master\rand.c 53
Error[Pe169]: expected a declaration E:\Downloads\msp430-rng-master\rand.c 54
Warning[Pe012]: parsing restarts here after previous syntax error E:\Downloads\msp430-rng-master\rand.c 68
The code for testing is:
#include <msp430g2553.h>
#include <signal.h>
#include <isr_compat.h>
#include "rand.h"
#define LED_OUT P1OUT
#define LED_DIR P1DIR
#define LED_RED BIT0
#define LED_GREEN BIT6
#define BLINK_DELAY 1200 // 200 ms at 6 KHz
#define BITS_RAND 16
#define BITS_PRAND 8 // Using only the MSB of the prand state
int failure = 0;
/**
* Set up the timers and blink!
*/
void prepare_to_blink() {
BCSCTL3 |= LFXT1S_2; // Set LF to VLO = 12 KHz
BCSCTL1 |= DIVA_1; // ACLK = LF / 2 = 6 KHz
TACCR0 = BLINK_DELAY; // Set the timer
TACTL = TASSEL_1 | MC_1; // TACLK = ACLK; up to CCR0
TACCTL1 = CCIE | OUTMOD_3; // TA1 interrupt enable; PWM set/reset
__bis_SR_register(LPM3_bits | GIE); // LPM3 w/ interrupt
}
int interrupt(TIMERA1_VECTOR) blink_LED (void) {
TACCTL1 &= ~CCIFG; // Unset interrupt flag
if (failure) // Toggle LEDs
LED_OUT ^= LED_RED;
else
LED_OUT ^= LED_GREEN;
}
/******************************************************************************
* Monobit
*
* SP 800-22 Rev. 1a
* http://csrc.nist.gov/publications/nistpubs/800-22-rev1a/SP800-22rev1a.pdf
******************************************************************************/
/* The hardware RNG is slow, so limit test to 400 bits. */
#define MONOBIT_TIMES_RAND 25 // 400 / BITS_RAND
/* Each 8-bit number tested with monobit contributes 8 bits, so in the worst
* case, the signed 16-bit bucket can store information about this many
* numbers: */
#define MONOBIT_TIMES_PRAND 4095 // (2 ^ 15 - 1) / BITS_PRAND
/* The maximum absolute value of the sum bucket after a monobit test, where
* 0.01 is the minimum P-value and inverfc is the inverse of the complementary
* error function. */
#define MONOBIT_MAX_VAL_RAND 51 // inverfc(0.01) * sqrt(2) * sqrt(400)
#define MONOBIT_MAX_VAL_PRAND 466 // inverfc(0.01) * sqrt(2) * sqrt(2 ^ 15 - 1)
/**
* Monobit test for rand().
*
* Returns 0 on success; otherwise otherwise.
*/
int monobit_rand() {
int sum = 0;
int i, j;
for (i = 0; i < MONOBIT_TIMES_RAND; i++) {
int r = rand();
/* Add up all the bits, taking 0 to mean -1. */
for (j = 0; j < BITS_RAND; j++) {
sum += r & 0x1 ? 1 : -1;
r >>= 1;
}
}
if (sum < 0)
sum = 0 - sum; // Absolute value
return sum > MONOBIT_MAX_VAL_RAND;
}
/**
* Monobit test for prand().
*
* Returns 0 on success; otherwise otherwise.
*/
int monobit_prand() {
int state = rand();
int sum = 0;
int i, j;
for (i = 0; i < MONOBIT_TIMES_PRAND; i++) {
int r = state >> (16 - BITS_PRAND); // Ignore the least significant bits
/* Add up all the bits, taking 0 to mean -1. */
for (j = 0; j < BITS_PRAND; j++) {
sum += r & 0x1 ? 1 : -1;
r >>= 1;
}
state = prand(state);
}
if (sum < 0)
sum = 0 - sum; // Absolute value
return sum > MONOBIT_MAX_VAL_PRAND;
}
/**
* Store the failure code on the top of the stack and alternate flashing the
* LEDs to signify failure.
*
* Never returns!
*/
void fail(int code) {
asm("push %0" : : "r" (code));
failure = 1;
LED_OUT &= ~LED_GREEN;
prepare_to_blink();
}
/**
* Run though all the tests.
*
* Both LEDs are lit up while testing, and one will blink once the tests are
* done, depending on the outcome.
*/
void main() {
LED_DIR |= LED_RED | LED_GREEN;
LED_OUT |= LED_RED | LED_GREEN;
if (monobit_rand())
fail(0xdead);
if (monobit_prand())
fail(0xbeef);
LED_OUT &= ~LED_RED;
prepare_to_blink();
}
And the list of errors when compiling:
Warning[Pa050]: non-native end of line sequence detected (this diagnostic is only issued once) E:\Downloads\msp430-rng-master\rand.h 1
Error[Pe169]: expected a declaration E:\Downloads\msp430-rng-master\test.c 34
Warning[Pe012]: parsing restarts here after previous syntax error E:\Downloads\msp430-rng-master\test.c 116
Warning[Pe1051]: standard requires that parameter "TIMERA1_VECTOR" be given a type by a subsequent declaration ("int" assumed) E:\Downloads\msp430-rng-master\test.c 34
Error[Pe130]: expected a "{" E:\Downloads\msp430-rng-master\test.c 117
Warning[Pe940]: missing return statement at end of non-void function "interrupt" E:\Downloads\msp430-rng-master\test.c 117
Error[Pe018]: expected a ")" E:\Downloads\msp430-rng-master\test.c 126
Warning[Pe223]: function "monobit_rand" declared implicitly E:\Downloads\msp430-rng-master\test.c 144
Warning[Pe223]: function "monobit_prand" declared implicitly E:\Downloads\msp430-rng-master\test.c 147
You have incorrect syntax. Please see the following line:
unsigned int rand(); {
This line should read:
unsigned int rand() {
Edit
In your test code, you have the following:
int interrupt(TIMERA1_VECTOR) blink_LED (void) {
I have never seen an interrupt service routine defined in this way. Instead it should be defined (in IAR EW430) like this:
#pragma vector=TIMERA1_VECTOR
__interrupt void blink_LED(void) {
I am trying to get a pic16 controller to run an initialization function that displays some text on an LCD only once and then goes on to display other things
The LCD output is working fine the problem is that the initialization function keeps executing. What am I doing wrong ?
/*
* File: main.c
*
* Created on Sep 1, 2013, 12:09 PM
*/
#include <pic.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include "delay.h"
__CONFIG(WDTE_ON & PWRTE_ON & MCLRE_ON & BOREN_ON & FOSC_INTRCIO );
static int exec_counter = 0;
#define set_bit(ADDRESS,BIT) (ADDRESS |= (1<<BIT)) // bit mask macros
#define clear_bit(ADDRESS,BIT) (ADDRESS &= ~(1<<BIT))
#define flip_bit(ADDRESS,BIT) (ADDRESS ^= (1<<BIT))
#define test_bit(ADDRESS,BIT) (ADDRESS & (1<<BIT))
#define E RC4 // Define the LCD Control Pins
#define RS RC5
int i; // Use Global Variables for Debug
LCDWrite(int LCDData, int RSValue)
{
PORTC = (LCDData >> 4) & 0x0F; // Get High 4 Bits for Output
RS = RSValue;
E = 1; E = 0; // Toggle the High 4 Bits Out
PORTC = LCDData & 0x0F; // Get Low 4 Bits for Output
RS = RSValue;
E = 1; E = 0; // Toggle the Low 4 Bits Out
if ((0 == (LCDData & 0xFC)) && (0 == RSValue))
DelayMs(5);
else
DelayUs(200);
} //
void writeLines(char top[],char bottom[]){
for (i = 0; top[i] != 0; i++) // Write Line 1
LCDWrite(top[i], 1);
LCDWrite(0b11000000, 0); // Move Cursor to the Second Line
for (i = 0; bottom[i] != 0; i++)// Write Line 2
LCDWrite(bottom[i], 1);
}
int countelems(char arr[]){
for (i = 0; arr[i] != 0; i++){}
return i;
}
void pad_number(char number[],char numberout[],char unit[]){
int size_n = countelems(number); // get length of number array by reference
int size_u = countelems(unit); // get length of unit array by reference
int size = size_u + size_n + 1; // calculate total size of text with 1 space between number and unit
int L_space = floor((16-size)/2)-1; // calculate space required on left side of display to center text
for (i = 0; i <= 15; i++)
numberout[i] = 0b10100000; // fill output char array with spaces
for (i = 0; i <= (size_n); i++){
numberout[i+(L_space+1)] = number[i]; // fill output char array with number
}
numberout[L_space+size_n+1] = 0b10100000; // put space in output char array between number and unit
for (i = 0; i <= size_u; i++){
numberout[i+(L_space+size_n+2)] = unit[i]; // fill output char array with unit
}
}
void pad_text(char text[],char textout[]){
int size = countelems(text); // get length of char array by reference
int L_space = floor((16-size)/2); // calculate space required on left side of display to center text
for (i = 0; i <= 15; i++)
textout[i] = 0b10100000; // fill output char array with spaces
for (i = 0; i <= 15; i++){
if( i >= L_space && i <= (L_space+size)){
textout[i] = text[i-L_space]; // fill middle of output char array with text
}
}
}
void getAnalog(int channel,char parameter[], char unit[]){
char output_parameter[16];
char output_number[16];
char number[16];
ADCON0 = channel << 2; // select channel
//set_bit(ADCON0,7); // set ADFM flag so LSB is bit 0 of ADRESL
set_bit(ADCON0,0); // switch ADC on = set ADON flag 0b00000001
sampleTime(); // wait required aquisition time
set_bit(ADCON0,1); // start conversion = set GO/DONE bit
while(test_bit(ADCON0,1)){/* wait for ADC to complete conversion */;}
int ADCresult = (ADRESL+ADRESH)/10; // get result from ADC
itoa(number,ADCresult,10); // convert ADC result to charstring
LCDWrite(0b00000001, 0); // Clear LCD
pad_text(parameter,output_parameter);
pad_number(number,output_number,unit);
writeLines(output_parameter, output_number);
}
void init(){
DelayMs(20); // Wait for LCD to Power Up
PORTC = 3; // Start Initialization Process
E = 1; E = 0; // Send Reset Command
DelayMs(5);
E = 1; E = 0; // Repeat Reset Command
DelayUs(200);
E = 1; E = 0; // Repeat Reset Command Third Time
DelayUs(200);
PORTC = 2; // Initialize LCD 4 Bit Mode
E = 1; E = 0;
DelayUs(200);
LCDWrite(0b00101000, 0); // LCD is 4 Bit I/F, 2 Line
LCDWrite(0b00000001, 0); // Clear LCD
LCDWrite(0b00000110, 0); // Move Cursor After Each Character
LCDWrite(0b00001110, 0); // Turn On LCD and Enable Cursor
// "0123456789012345"
writeLines( " INITIALIZE ",
" TEXT ");
}
void main(void) {
OPTION_REG |= 0x7; // set prescaler to 1:128 or 2.3 Seconds
OPTION_REG |= 0x8; // assign prescaler to WDT
TRISA = 0b00000101; // configure PORTA set RA0 and RA2 to analog input;
ANSEL = 0b00000101; // disable input buffers if I/O pins RA0 and RA2
TRISC = 0; // configure PORTC as output
ADCON1 = 0; // select FOSC2
if (exec_counter == 0){
exec_counter++;
init();
DelayS(4);
}
PORTC = 0;
while (1) {
getAnalog(0,"VELOCITY","KM/H");
DelayS(4);
getAnalog(2,"ACCELERATION","M/S^2");
DelayS(4);
}
return;
}
/*
* File: delay.c
*
* Created on Sep 3, 2013, 12:09 PM
*/
#include "delay.h"
#include <pic.h>
#define _XTAL_FREQ 4000000
void DelayMs(unsigned char cnt)
{
#if XTAL_FREQ <= 2MHZ
do {
DelayUs(996);
} while(--cnt);
#endif
#if XTAL_FREQ > 2MHZ
unsigned char i;
do {
i = 4;
do {
DelayUs(250);
} while(--i);
} while(--cnt);
#endif
}
void DelayS(unsigned int count){
for (int i=0; i<=count;i++){
NOP();
CLRWDT();
DelayMs(1000);
}
}
void sampleTime(){
// TC = – 10pF ( 1k Ω + 7k Ω + 1k Ω ) ln(0.0004885)
// = 0.686 μS
// TACQ = 5μS + 0.686μS + [ ( 50°C- 25°C ) ( 0.05μ S /°C ) ]
// = 6.936 μS /
// 1 instruction cycle = 4μS # 1 mHz
// 1 instruction cycle = 1μS # 4 mHz
// 1 instruction cycle = 500nS # 8 mHz
// 1 instruction cycle = 200nS # 20 mHz
// TACQ # 1 mHz is 6.936 μS / 4 μS or ~ 2 instruction cycles
// TACQ # 4 mHz is 6.936 μS / 1 μS or ~ 7 instruction cycles
// TACQ # 8 mHz is 6.936 μS / 0.5 μS or ~ 14 instruction cycles
// TACQ # 20 mHz is 6.936 μS / 0.2 μS or ~ 35 instruction cycles
DelayUs(8);
}
The char number[] = ""; array is very small, yet you use it in itoa(), thus overwriting random memory.