I am struggling to understand this code [closed] - c

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
I spent more time and struggling to understand this code.
I edited and manage to display the data on LCD but
I would like to understand it.
I have added some comment to the code to show my bit understanding.
// Control 16 character LCD (2x8 chars) with 4 bit interface
// Copyright (C) 2012 Joonas Pihlajamaa. Released to public domain.
// No warranties, use at your own responsibility.
#include <avr/io.h>
#define F_CPU 12000000UL // 12 MHz
#include <util/delay.h>
#define DATA_PORT_DIR DDRB // macro for data port direction
#define DATA_PORT PORTB //macro for data port
#define DATA_PORT_IN PINB //macro for data port pin
#define RW_PIN (1<<PD4) // PORTD Pin4 is defined as for RW
#define RS_PIN (1<<PD5) // PORTD Pin5 is defined as for RS
#define EN_PIN (1<<PD6) // PORTD Pin6 is defined as for EN
// macro or something else? confused?
#define SET_CTRL_BIT(pin) (PORTD |= pin)
#define CLEAR_CTRL_BIT(pin) (PORTD &= ~pin)
// assumes EN_PIN is LOW in the beginning
void lcd_write(char rs, unsigned char data)
{
if(DATA_PORT_DIR != 0xFF) // condition to test if DATA_PORT_DIR is true
//make DATA_PORT_DIR as output to write data to ldc
DATA_PORT_DIR = 0xFF;
CLEAR_CTRL_BIT(RW_PIN);
if(rs)
SET_CTRL_BIT(RS_PIN);
else
CLEAR_CTRL_BIT(RS_PIN);
DATA_PORT = data;
_delay_us(2);
SET_CTRL_BIT(EN_PIN);
_delay_us(2);
CLEAR_CTRL_BIT(EN_PIN);
}
unsigned char lcd_read(char rs)
{
unsigned char data;
if(DATA_PORT_DIR != 0)
DATA_PORT_DIR = 0;
SET_CTRL_BIT(RW_PIN);
if(rs)
SET_CTRL_BIT(RS_PIN);
else
CLEAR_CTRL_BIT(RS_PIN);
_delay_us(2);
SET_CTRL_BIT(EN_PIN);
_delay_us(2);
data = DATA_PORT_IN;
CLEAR_CTRL_BIT(EN_PIN);
return data;
}
void lcd_wait()
{
while(lcd_read(0) & 0x80); // wait until display is ready
}
void lcd_init()
{
_delay_ms(50); // wait for VDD to rise
lcd_write(0, 0x30);
_delay_ms(5);
lcd_write(0, 0x30);
_delay_ms(1); // _delay_us(120);
lcd_write(0, 0x30);
_delay_ms(1); // _delay_us(120);
lcd_write(0, 0x38); // 2 lines, normal font
_delay_ms(1);
lcd_write(0, 0xC); // display on
_delay_ms(1);
lcd_write(0, 1); // display clear
_delay_ms(1);
lcd_write(0, 0x6); // increment, don't shift
_delay_ms(1);
}
void lcd_puts(char * string)
{
char i;
lcd_write(0, 0x80); // move to 1st line
lcd_wait();
for(i=0; i<8; i++)
{
if(string[i] == '\0')
return;
lcd_write(1, string[i]);
lcd_wait();
}
lcd_write(0, 0x80+0x40); // move to 2nd line
lcd_wait();
for(i=8; i<16; i++)
{
if(string[i] == '\0')
return;
lcd_write(1, string[i]);
lcd_wait();
}
}
int main(void)
{
unsigned char i = 0;
char message[] = "nn Mississippi..";
DDRD = RS_PIN + EN_PIN + RW_PIN + LED_PIN; // Control outputs
DDRB = 0xFF; // Port B as DB0..DB7
lcd_init();
lcd_puts("Hello, World!!!");
_delay_ms(2000);
while(1)
{
if(++i >= 100)
i = 1;
if(i >= 10)
message[0] = i/10+'0';
else
message[0] = ' ';
message[1] = i%10+'0';
lcd_puts(message);
_delay_ms(1000);
}
return 1;
}

These define constants that have only the bit specified on
#define RW_PIN (1<<PD4) // PORTD Pin4 is defined as for RW
#define RS_PIN (1<<PD5) // PORTD Pin5 is defined as for RS
#define EN_PIN (1<<PD6) // PORTD Pin6 is defined as for EN
These Macros can then use the above can be used to set the bit (by OR'ing it on) or clearing the bit by using AND with the 1's complement of the constant (all bits on but one).
// macro or something else? confused?
#define SET_CTRL_BIT(pin) (PORTD |= pin)
#define CLEAR_CTRL_BIT(pin) (PORTD &= ~pin)
Here is what it looks that the write is doing: If first puts all the port bits in output mode (so it can write the data). It then sets RW pin low (I assume to put it in write mode) and resets the display (if rs is set) by toggling the RS bit. It then loads the data into the DATA_PORT and toggles the EN pin (I assume to load it).
// assumes EN_PIN is LOW in the beginning
void lcd_write(char rs, unsigned char data)
{
if(DATA_PORT_DIR != 0xFF) // condition to test if DATA_PORT_DIR is true
//make DATA_PORT_DIR as output to write data to ldc
DATA_PORT_DIR = 0xFF;
CLEAR_CTRL_BIT(RW_PIN);
if(rs)
SET_CTRL_BIT(RS_PIN);
else
CLEAR_CTRL_BIT(RS_PIN);
DATA_PORT = data;
_delay_us(2);
SET_CTRL_BIT(EN_PIN);
_delay_us(2);
CLEAR_CTRL_BIT(EN_PIN);
}
Here is what it looks that the read is doing: If first puts all the port bits in input mode (so it can read the data). It then sets RW pin high (I assume to put it in read mode) and resets the display (if rs is set) by toggling the RS bit. It then sets the EN bit and fetches the data from the DATA_PORT and turns the EN pin off again.
unsigned char lcd_read(char rs)
{
unsigned char data;
if(DATA_PORT_DIR != 0)
DATA_PORT_DIR = 0;
SET_CTRL_BIT(RW_PIN);
if(rs)
SET_CTRL_BIT(RS_PIN);
else
CLEAR_CTRL_BIT(RS_PIN);
_delay_us(2);
SET_CTRL_BIT(EN_PIN);
_delay_us(2);
data = DATA_PORT_IN;
CLEAR_CTRL_BIT(EN_PIN);
return data;
}
Is that enough for you to figure out what the rest is doing?

Related

synthesizer - recording pressed keypad

I have to build synthesizer and I am using C for programing my ATmega128A. I need to record the keypads pressed and play them after some time. For keypad press I am using polling in the main.c. For playing the keypads I am using Timer1. Every time when the timer expires I am storing the keypad frequency and increment counter for it. During play, I calculate the duration firstle, then play it for that interval. When I want to play the stored song, it ticks for some time and starts to make a long sound.
Also, I want to make possible to press, record and palay simultanous keypads. Can you suggest some algorithm for this?
main.c
#include <avr/io.h>
#include <avr/interrupt.h>
#include "keypad.h"
unsigned char temp; // to get keyboard input to play a note
unsigned char option; //to choose the embedded music to play
#define DELAY 1000
int main(void)
{
DDRG = 0xff; // To send sound to BUZ speakers (BUZ is connected to PG.4)
DDRD = 0x00; // Make it input, to get corresponding key to play a note
PORTD = 0xff; // All bits are 1s, so no button is pressed in the beginning
sei(); //Set Interrupt flag as enabled in SREG register
option = no_music; //No music is played on startup, this is default mode for free playing
// This loop keeps playing forever, so the main functionality
// of the program is below
DDRB = 0xff;
DDRD = 0x00; //ready for input
while(1)
{
temp = PIND; //store keyboard input for temporary variable
//PORTB = PIND;
switch(temp)
{
case 254: { // if 1st pin of PORTD is pressed
play_note(notes5[0]); // play corresponding note from octave 5 for 200ms
break;
}
case 253: { // if 2nd pin of PORTD is pressed
play_note(notes5[1]);
break;
}
case 251: { // if 3rd pin of PORTD is pressed
play_note(notes5[2]);
break;
}
case 247: { // if 4th pin of PORTD is pressed
play_note(notes5[3]);
break;
}
case 239: { // if 5th pin of PORTD is pressed
play_note(notes5[4]);
break;
}
case 223: { // if 6th pin of PORTD is pressed
play_note(notes5[5]);
break;
}
case 191: { // if 7th pin of PORTD is pressed
play_note(notes5[6]);
break;
}
case 127: {
if(isRecordingEnabled){
disableRecording();
//toggling LED as the sign of playing the record
toggleLED();
custom_delay_ms(DELAY);
toggleLED();
custom_delay_ms(DELAY);
custom_delay_ms(DELAY);
play_record();
}else{
//toggling LED as the sign of record start
toggleLED();
enableRecording();
}
}
}
}
return 0;
}
keypad.c
#include "structs.h"
#include "play.h"
#define F_CPU 16000000UL // 16 MHz
#include <util/delay.h>
#define BUFFER_SIZE 100
struct played_note buffer[BUFFER_SIZE];
int i = 0;
int8_t isRecordingEnabled = 0;
int8_t recordIndex = 0;
int8_t pressedNote;
int8_t isPressed = 0;
int8_t isPlaying = 0;
unsigned int ms_count = 0;
#define INTERVAL 100
#define DELAY_VALUE 0xFF
ISR(TIMER1_COMPA_vect){
// every time when timer0 reaches corresponding frequency,
// invert the output signal for BUZ, so it creates reflection, which leads to sound generation
//check whether the key was pressed because
//when the recording is enabled the interrupt is working make sound
if(isPressed || isPlaying)
PORTG = ~(PORTG);
if(isRecordingEnabled){
if(PIND == DELAY_VALUE)
pressedNote = DELAY_VALUE;
if(i == 0){
buffer[i].note = pressedNote;
buffer[i].counter = 0;
i++;
}else{
if(buffer[i - 1].note == pressedNote){
//the same note is being pressed
buffer[i - 1].counter++;
}else{
buffer[i++].note = pressedNote;
buffer[i].counter = 0;
}
}
}
}
void initTimer1(){
TIMSK = (1 << OCIE1A); //Timer1 Comparator Interrupt is enabled
TCCR1B |= (1 << WGM12) | (1 << CS12); //CTC mode, prescale = 256
}
void stopTimer1(){
TIMSK &= ~(1UL << OCIE1A);
TCCR1A = 0; //stop the timer1
TIFR = (1 << OCF1A); //Clear the timer1 Comparator Match flag
}
void enableRecording(){
isRecordingEnabled = 1;
i = 0;
ms_count = 0;
initTimer1();
}
void disableRecording(){
isRecordingEnabled = 0;
stopTimer1();
}
//Timer1A
void play_note_during(unsigned int note, unsigned int duration){
OCR1A = note;
pressedNote = note;
isPressed = 1;
initTimer1();
custom_delay_ms(duration);
stopTimer1();
isPressed = 0;
}
//Timer1A
void play_note(unsigned int note){
play_note_during(note, INTERVAL);
}
void play_record(){
isPlaying = 1;
recordIndex = 0;
int duration;
while(recordIndex < i){
PORTB = buffer[return].counter << 8;
duration = INTERVAL * buffer[recordIndex].counter;
if(buffer[recordIndex].note == DELAY_VALUE)
custom_delay_ms(duration);
else
play_note_during(buffer[recordIndex].note, duration);
recordIndex++;
}
isPlaying = 0;
}
Further references can be found in the following github repository:
https://github.com/bedilbek/music_simulation
Actually your question about how to record and replay key presses, should be anticipated by another question about how to play several sounds simultaneously.
Now you're using just PWM output with variable frequency. But this allows you to generate only a single wave of a square form. You cannot play two notes (except of using another timer and another PWM output).
Instead of that, I suggest you to use PWM at the highest frequency and apply a RC or LC filters to smooth high-frequency PWM signal into a waveform, and then apply that waveform to the amplifier and to the speaker to make a sound.
Having this approach you make generate different waveforms, mix them together, make them louder or more silent and even apply a "fade-out" effect to make them sound like a piano.
But your question is not about how to generate that kind of wave-forms, so if you want to know you should start another question.
So, returning to your question.
Instead of having single procedure, which is starting note, holding a pause and only then returning back; I suggest you to have a several procedures, one play_note(note) - which will start playing a note and returns immediately (while note continue playing). And, of course, stop_note(note) - which will stop specified note, if it is played. Also I suggest you to pass a note number, rather than frequency or timer period to the play function. Let's assume 0 is the lowest possible note (e.g. C2), and then they go sequentially by semitones: 1 - C#2, 2 - D2, .... 11 - B2, 12 - C3 ... etc.
For the first time, you may remake your single-note playing procedures to match that.
// #include <avr/pgmspace.h> to store tables in the flash memory
PROGMEM uint16_t const note_ocr_table[] = {
OCR1A_VALUE_FOR_C2, OCR1A_VALUE_FOR_C2_SHARP, ... etc
}; // a table to map note number into OCR1A value
#define NOTE_NONE 0xFF
static uint8_t current_note = NOTE_NONE;
void play_note(uint8_t note) {
if (note >= (sizeof(note_ocr_table) / sizeof(note_ocr_table[0])) return; // do nothing on the wrong parameter;
uint16_t ocr1a_val = pgm_read_word(&note_ocr_table[note]);
TIMSK = (1 << OCIE1A); //Timer1 Comparator Interrupt is enabled // why you need this? May be you want to use just inverting OC1A output?
TCCR1B |= (1 << WGM12) | (1 << CS12); //CTC mode, prescale = 256 // you may want to use lesser prescalers and higher OCR1A values ?
OCR1A = ocr1a_val;
if (TCNT1 >= ocr1a_val) TCNT1 = 0; // do not miss the compare match when ORC1A is changed to lower values;
current_note = note;
}
void stop_note(uint8_t note) {
if (note == current_note) { // ignore stop for non-current note.
TIMSK &= ~(1UL << OCIE1A);
TCCR1A = 0; //stop the timer1
TIFR = (1 << OCF1A); //Clear the timer1 Comparator Match flag
current_note = NOTE_NONE; // No note is playing
}
}
so, now your task is very simple: you should just pull the state of the keys periodically, let's say 61 times per second (based on the some 8-bit timer with 1:1024 prescaler overflow), and they to note: which keys are changed their state. If some key is pressed, you call play_note to start coressponding note. If the key is released, you call stop_note, also you're counting how many timer cycles passed since the last event.
When recording, you just push those events into array "key X is pressed" or "key X is released" or "X timer cycles expired".
When playing back, you just performing a backward process, scaning your array, and executing commands: calling play_note, stop_note, or waiting exact amount of timer cycles, if it is a pause.
Instead of writing giant switch statement, you may also use a table to scan the buttons
// number of element in the port-state arrays
#define A 0
#define B 1
#define C 2
#define D 3
#define E 4
#define F 5
typedef struct {
port_index uint8_t;
mask uint8_t;
} KeyLocation;
PROGMEM KeyLocation const key_location[] = {
{ B, (1 << 1) }, // where C2 is located, e.g. PB1
{ E, (1 << 3) }, // where C#2 is located, e.g. PE3
...
}
uint16_t ticks_from_prev_event = 0;
uint8_t port_state_prev[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0XFF};
for (;;) { // main loop
wait_tick_timer_to_overflow();
// latching state of the pins
uint8_t port_state[6] = {PINA, PINB, PINC, PIND, PINE, PINF};
for (uint8_t i = 0 ; i < (sizeof(key_location) / sizeof(key_location[0])) ; i++) {
uint8_t port_idx = pgm_read_byte(&key_location[i].port_index);
uint8_t mask = pgm_read_byte(&key_location[i].mask);
if ((port_state[port_idx] & mask) != (port_state_prev[port_idx] & mask)) { // if pin state was changed
if (is_recording && (ticks_from_prev_event > 0)) {
put_into_record_pause(ticks_from_prev_event); // implement it on your own
}
if ((port_state[port_idx] & mask) == 0) { // key is pressed
play_note(i);
if (is_recording) {
put_into_record_play_note(i); // implement
}
} else { // key is released
stop_note(i);
if (is_recording) {
put_into_record_stop_note(i); // implement
}
}
}
}
// the current state of the pins now becomes a previous
for (uint8_t i = 0 ; i < (sizeof(port_state) / sizeof(port_state[0])) ; i++) {
port_state_prev[i] = port_state[i];
}
if (ticks_from_prev_event < 65535) ticks_from_prev_event++;
}
put_into_record_... implement as you wish.
the playback would be the same simple (below just the template, you'll suggest from the function name what they should do)
while (has_more_data_in_the_recording()) {
if (next_is_play()) {
play_note(get_note_from_recording())
} else if (next_is_stop()) {
play_note(get_note_from_recording())
} else {
uint16_t pause = get_pause_value_from_recording();
while (pause > 0) {
pause--;
wait_tick_timer_to_overflow();
}
}
}
This approach gives you two benefits:
1) It doesn't matter how many notes the playing module can play, the keys are recorder while they are pressed and released, so, all simultaneous keys will be recorded and replayed in the same time.
2) It doesn't matter how many notes are pressed in exact the same moment. Since pause and key events are recorded separately, during the replay all the same-time key presses will be replayed in the same time, without an "arpeggio" effect

No output for Embedded application with PIC12, MPLAB and UART

I am working on RGB LED project and that's controlled by a PIC12F1572. The software that I am using is MPLAB IDE with the HiTech C compiler. The plan is to use serial communication to send LED RGB combination data commands to the PIC to be stored in a variable that will make it perform the LED blink and glowing I have been able to establish UART communication.Every function or step I code is right by syntax and works on linux command line terminal if I compile..
And it fails if I try to simulate using register injection in MPLAB.I wanted to run it in simulation also (anyone knows how register injection actuallly works in MPLAB?)
The problem I face together when I try to debug . it compiles but doesn't work
here is my code :
Any idea or hint about the problem will be highly appreciated.
I personally fee that placing the code [hierarchical way] may be wrong
Thanks!
#include <xc.h>
#include "mcc.h"
#include "LED.h"
#include "tmr0.h"
#include "interrupt_manager.h"
void SetLedColor(uint16_t R_color, uint16_t G_color, uint16_t B_color);
void main(void)
{
uint8_t data, i, j;
uint16_t R_value, G_value, B_value;
uint8_t value;
uint8_t RX_Buffer[FRAMESIZE] ,RGB_data[6] ,HEX_data[6];
// initialize the device
SYSTEM_Initialize();
INTERRUPT_GlobalInterruptEnable(); // Enable the Global Interrupts
INTERRUPT_PeripheralInterruptEnable(); // Enable the Peripheral Interrupts
while (1)
{
// EUSART_Write(0x61);
while (!RCIF)
{
data = EUSART_Read(); // Read received character
for (i = 0; i < FRAMESIZE; i++)
{
RX_Buffer[i] = data;
}
EUSART_Write(data);
}
//check if any data is received
for (j = 0; j = 5; j++) // get the RGB value in the separate array
{
RGB_data[j] = RX_Buffer[j + 3];
HEX_data[value] = RGB_data[j] / 16;
}
if (RX_Buffer[0] == 'R' && RX_Buffer[FRAMESIZE - 1] == '\n')
{
//ASCII to HEX separate values
// uint32_t number = (uint32_t)strtol(HEX_data, NULL, 16);
// R_value = number >>16;
// G_value = (number & 0xffff) >> 8;
// B_value = (number & 0x0000FF);
R_value = (uint16_t) atoh(HEX_data[0], HEX_data[1]);
G_value = (uint16_t) atoh(HEX_data[2], HEX_data[3]);
B_value = (uint16_t) atoh(HEX_data[4], HEX_data[5]);
}
SetLedColor(R_value, G_value, B_value);
}
}
void SetLedColor(uint16_t R_color, uint16_t G_color, uint16_t B_color)
{
if (R_color == 0xFF)
{
LATAbits.LATA2 = 1;
}
else
{
LATAbits.LATA2 = 0;
}
if (G_color == 0xFF)
{
LATAbits.LATA4 = 1;
}
else
{
LATAbits.LATA4 = 0;
}
if (B_color == 0xFF)
{
LATAbits.LATA5 = 1;
}
else
{
LATAbits.LATA5 = 0;
}
}
So till the receiving the UART frame and echoed back and from the storing data make LED blink , I am able to succeed and this is what I wanted for primary step here by hierarchical way
#include "mcc_generated_files/mcc.h"
#include <stdlib.h>
#include <stdio.h>
#include "atoh.h"
#include "LED.h"
#define _XTAL_FREQ 16000000
#define FRAMESIZE 19
void main(void)
{
uint8_t data,i,j,got_char;
uint8_t R_value, G_value ,B_value;
uint8_t value;
uint8_t RX_Buffer[FRAMESIZE];
uint8_t RGB_data[6] ,HEX_data[6];
// initialize the device
SYSTEM_Initialize();
INTERRUPT_GlobalInterruptEnable(); // Enable the Global Interrupts
INTERRUPT_PeripheralInterruptEnable(); // Enable the Peripheral Interrupts
while (1)
{
if (EUSART_DataReady)
{
for (i = 0; i<FRAMESIZE; i++)
{
RX_Buffer[i] = EUSART_Read();
if (RX_Buffer[i] == '\n')
break;
}
RX_Buffer[i] = '\n'; //append '\n' at the end of stoaring array for detection of frame
RX_Buffer[i+1] = '\0'; // End of an array
EUSART_WriteAnArrayOfBytes(RX_Buffer);
if(RX_Buffer[0]=='R' && RX_Buffer[FRAMESIZE-2] == '\n') //check for correct frame
{
LATAbits.LATA2 = 1;
__delay_ms(2000);
LATAbits.LATA2 = 0;
__delay_ms(1000);
}
}
}

GPIO interrupt for different pins in PSoC 1

I have faced a problem connected with GPIO interrupt.
The task is to make a simple UI interface, so I need to use 3 buttons.
The problem is that I don't understand how to use GPIO interrupt for different pins and all my buttons work the same way.
here is the code:
#include <m8c.h> // part specific constants and macros
#include "PSoCAPI.h" // PSoC API definitions for all User Modules
#include <stdio.h>
#include <stdlib.h>
typedef struct {
int value; // the actual value which is used in the module
char string[16]; // string that is printed in LCD for user
} UI_ELEMENT;
#define FIRST_LEVEL 3
#define SECOND_LEVEL 3
#define PWM 0
#define PGA 1
#define ADC 2
#define PWM_STATE 0
#define PWM_PERIOD 1
#define PWM_WIDTH 2
#define PWM_STATE_OFF 0
#define PWM_STATE_ON 1
volatile int buttonRightPressed = 0;
#pragma interrupt_handler buttonRightInt
void buttonRightInt(void){
// disable button interrupt
M8C_DisableIntMask(INT_MSK0, INT_MSK0_GPIO);
buttonRightPressed = 1;
}
void initialize_LCD(void){
LCD_Position(0,0);
LCD_PrCString("PWM");
LCD_Position(1,0);
LCD_PrCString("< select >");
}
void update_LCD(int* lvl1){
if (*lvl1 == PWM || *lvl1 == 3){
LCD_Position(0,0);
LCD_PrCString("PWM");
*lvl1 = 0;
}
else if (*lvl1 == PGA){
LCD_Position(0,0);
LCD_PrCString("PGA");
}
else if (*lvl1 == ADC){
LCD_Position(0,0);
LCD_PrCString("ADC");
}
}
void main(void)
{
UI_ELEMENT userInterface[FIRST_LEVEL][SECOND_LEVEL];
int level_1_steper = PWM;
int i;
M8C_EnableGInt ; // Uncomment this line to enable Global Interrupts
PWM8_EnableInt();
LCD_Start();
M8C_EnableIntMask(INT_MSK0, INT_MSK0_GPIO);
initialize_LCD(); // set 'PWM' for upper row, '< select >' for lower row
while (1){
if (buttonRightPressed == 1){
for ( i = 0; i < 350; i++);
level_1_steper++;
update_LCD(&level_1_steper);
buttonRightPressed = 0;
// enable button interrupt again
M8C_EnableIntMask(INT_MSK0, INT_MSK0_GPIO);
}
}
}
Problem resolved! As usually solution is quite simple: use GPIO interrupt but test which button has been pressed. GPIO iterrupt:
void buttonInt(void){ // disable button interrupt
M8C_DisableIntMask(INT_MSK0, INT_MSK0_GPIO);
if (Right_Data_ADDR & Right_MASK) buttonRightPressed = 1;
if (Left_Data_ADDR & Left_MASK) buttonLeftPressed = 1;
if (Select_Data_ADDR & Select_MASK) buttonSelectPressed = 1;
}

USART embedded C. trigger character to store array

USART embedded c for atmega328p. trying to store an array of 10 characters of whatever user inputs after a certain character is received(in my case char $). This compiles for me but only outputs dollar signs when I input a string of chars using hercules utility reader. any help appreciated
the following is a copy of the code I am using
#define FOSC 16000000 // Clock Speed
#define BAUD 9600
#define MYUBRR FOSC/16/BAUD-1
#include <avr/io.h>
//#include <stdio.h>
char trig='$';
char arr[10];
//This function is used to initialize the USART
//at a given UBRR value
void USARTInit(unsigned int ubrr)
{
//Set Baud rate
UBRR0H = (ubrr>>8);
UBRR0L = ubrr;
//Enable The receiver and transmitter
UCSR0B = (1<<RXEN0)|(1<<TXEN0);
// Set fram format: 8data 2stopBit
UCSR0C = (1<<USBS0)|(3<<UCSZ00);
}
//This function is used to read the available data
//from USART. This function will wait untill data is
//available.
unsigned char USARTReadChar( void )
{
//Wait untill a data is available
while(!(UCSR0A & (1<<RXC0)))
{
//Do nothing
}
//Now USART has got data from host
//and is available is buffer
return UDR0;
}
//This function writes the given "data" to
//the USART which then transmit it via TX line
void USARTWriteChar(unsigned char data)
{
//Wait untill the transmitter is ready
while(!(UCSR0A & (1<<UDRE0)))
{
//Do nothing
PORTD ^= 1 << PINB2;
}
//Now write the data to USART buffer
UDR0 = data;
}
int main(void)
{
DDRB |= 1 << PINB2;
//Varriable Declaration
char data;
USARTInit(MYUBRR);
//Loop forever
while(1)
{
//Read data
data = USARTReadChar();
int i =0;
//if incoming data is a dollar sign(trig),
if(data==trig)
{
//start a loop to collect data from buffer
for(i=0;i<10;i++)
{
//array has 10 elements, will fill up the ith element as per for loop
arr[i]=data;
// printf("arrayoutput %c\n",arr[i]);
USARTWriteChar(data);
}
}
}
}
I edited the while loop as suggested by oleg but still cannot get it to return the array .the entire code is as follows:
#define FOSC 16000000 // Clock Speed
#define BAUD 9600
#define MYUBRR FOSC/16/BAUD-1
#include <avr/io.h>
#include <stdio.h>
char trig='$';
char arr[10];
//This function is used to initialize the USART
//at a given UBRR value
void USARTInit(unsigned int ubrr)
{
//Set Baud rate
UBRR0H = (ubrr>>8);
UBRR0L = ubrr;
//Enable The receiver and transmitter
UCSR0B = (1<<RXEN0)|(1<<TXEN0);
// Set fram format: 8data 2stopBit
UCSR0C = (1<<USBS0)|(3<<UCSZ00);
}
//This function is used to read the available data
//from USART. This function will wait untill data is
//available.
unsigned char USARTReadChar( void )
{
//Wait untill a data is available
while(!(UCSR0A & (1<<RXC0)))
{
//Do nothing
}
//Now USART has got data from host
//and is available is buffer
return UDR0;
}
//This function writes the given "data" to
//the USART which then transmit it via TX line
void USARTWriteChar(unsigned char data)
{
//Wait untill the transmitter is ready
while(!(UCSR0A & (1<<UDRE0)))
{
//Do nothing
PORTD ^= 1 << PINB2;
}
//Now write the data to USART buffer
UDR0 = data;
}
int main(void)
{
DDRB |= 1 << PINB2;
//Varriable Declaration
char data;
USARTInit(MYUBRR);
//Loop forever
//Read data
char input[10];
while(1){
data = USARTReadChar();
if(data == trig){
for(int i = 0; i < 10; i++){
//here we're saving 10 characters to input array
input[i] = USARTReadChar();
USARTWriteChar(input[i]);//tested without this also
}
}
}
}
Try to read chars in for() loop:
char input[10];
while(1){
data = USARTReadChar();
if(data == trig){
for(int i = 0; i < 10; i++){
//here we're saving 10 characters to input array
input[i] = USARTReadChar();
}
/* UPD: write stored array to console */
for(int i =0; i < 10; i++){
USARTWriteChar(input[i]);
}
/* those symbols are needed to emulate Enter button */
USARTWriteChar('\r');
USARTWriteChar('\n');
}
}
UPD: this code does exactly that you asked. It stores 10 chars in memory. To return them to console (utility reader) you have to use USARTWriteChar().

how to give a parameters to a function in C [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
I don't know how to give a parameters to a function. I wrote a body, as you can see in my program below. Any answers and explanations appreciated!
#include <avr/io.h>
#include <stdint.h>
// Ceramic Resonator
#ifndef F_CPU
#define F_CPU 3686400 // 4MHz
#endif
// UART
#define UART_BAUD_RATE 9600
#define UART_BAUD_CALC(UART_BAUD_RATE,F_OSC) ((F_CPU)/((UART_BAUD_RATE)*16L)-1)
int decode( int rcv[i], ... ){ !!!
int returnValue;
if ((rcv[0] == rcv[1]) && (rcv[0] == rcv[2]) && (rcv[1] == rcv[2])){
returnValue = 0;
//return UDR0;
}
else if (rcv[1] != rcv[2] && (rcv[0] == rcv[1])){
returnValue = 1;
//UDR0 = 01;
}
else if (rcv[1] != rcv[2] && (rcv[0] == rcv[2])){
returnValue = 2;
//UDR0 = 02;
}
else if (rcv[0] != rcv[1] && (rcv[1] == rcv[2])){
returnValue = 3;
//UDR0 = 03;
}
return returnValue;
}
int main(void){
// USART
UBRR0H =(uint8_t) (UART_BAUD_CALC(UART_BAUD_RATE,F_CPU) >>8);
UBRR0L =(uint8_t) UART_BAUD_CALC(UART_BAUD_RATE,F_CPU);
UCSR0B = (1<<RXEN0) | (1<<TXEN0); // enable receiver and transmitter,
UCSR0C = (3<<UCSZ00); // 8 bit (default: asynchronous, no parity, 1 stop-bit)
DDRC = (1<<5); // set data direction register bit 5 to one, this means PC5 is configured as output
PORTC = (1<<5); // set output value of PC5 to High-Level (Source Current, 5V to ground)
// VARIABLES
//uint8_t get;
// PROGRAM
unsigned char code[3] = {'x','y','z'}; // Here you need to write your code
unsigned char rcv[3]={'0','0','0'}; // received data
int i = 0;
int retVal;
while(1){
i = 0;
for(i=0;i<=2;i++){
// wait for empty transmit buffer
//while (!(UCSR0A & (1<<UDRE0)));
// wait for data to be received
while (!(UCSR0A & (1<<RXC0)));
/* put data into buffer, sends the data*/
{
code[i]= UDR0 ;
}
//while(1) // forever
//{
PORTC ^= (1<<5); //this is for LED
// get received data from buffer
rcv[i] = code[i];
}
retVal = decode(int rcv[i], ... ); !!!
// wait for empty transmit buffer
while (!(UCSR0A & (1<<UDRE0)));
// put data into buffer, sends the data
/*if ((rcv[0] == rcv[1]) && (rcv[0] == rcv[2]) && (rcv[1] == rcv[2]))*/
UDR0 = retVal;
}
}
I like #Ari's answer but I feel like I should add that you can use variable parameter lists if that's what you want. You can find a good tutorial here, but this would probably be more work that you require.
Edit:
I just noticed the // Ceramic resonator comment so I'm guessing you're in an Embedded environment in which case I would strongly recommend a simple pointer like #Ari suggested. The variable parameter list might not be fully implemented on your architecture.
You should put pointer to an array and maybe size of it:
change:
int decode( int rcv[i], ...)
to
int decode( unsigned char* rcv)
and
retVal = decode(int rcv[i], ... ); !!!
to
retVal = decode(rcv); //rcv is a pointer

Resources