Converting chars to int from serial port in C - c

I am using this source code to read from the serial port of a linux machine. I am able to read from the port, but all of the values are in ascii gibberish ( i am reading the input from an xbox controller). I know I am sending it correctly, i.e. i can see on my side I am sending -128 - 127 as a char, but when I am converting it on my linux machine using atoi its returning 0, or when I try to cast the data to int it returns -48 , equivalent to 0 in ascii.
Is there a way for me to convert the incoming ascii into a readable integer like 64 or -114? I appreciate any help, thank you.
#include <stdlib.h>
#include <stdio.h>
#ifdef _WIN32
#include <Windows.h>
#else
#include <unistd.h>
#endif
#include "rs232.h"
int main()
{
int i, n,
cport_nr=0, /* /dev/ttyS0 (COM1 on windows) */
bdrate=9600; /* 9600 baud */
unsigned char buf[4096];
char mode[]={'8','N','1',0};
if(RS232_OpenComport(cport_nr, bdrate, mode))
{
printf("Can not open comport\n");
return(0);
}
while(1)
{
n = RS232_PollComport(cport_nr, buf, 4095);
if(n > 0)
{
buf[n] = 0; /* always put a "null" at the end of a string! */
for(i=0; i < n; i++)
{
if(buf[i] < 32) /* replace unreadable control-codes by dots */
{
buf[i] = '.';
}
}
printf("received %i bytes: %s\n", n, (char *)buf);
}
#ifdef _WIN32
Sleep(100);
#else
usleep(100000); /* sleep for 100 milliSeconds */
#endif
}
return(0);
}

Related

Reading a 32k i2c eeprom from userland

I need to read an eeprom in an embedded device.
So far this "almost" worked:
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <fcntl.h>
#include <linux/i2c-dev.h>
#define READ_SIZE (256)
#define NB_PAGES (128)
void dump_to_file(const char *output_file_path,
const uint8_t *buffer, const int buffer_length)
{
int output_file = open(output_file_path, O_RDWR|O_APPEND|O_CREAT);
if (output_file < 0) {
printf("Failed opening output file %s\n", output_file_path);
return;
}
write(output_file, buffer, buffer_length);
}
int main(int argc, char *argv[])
{
/* got these values from i2cdetect */
const char *i2c_device = "/dev/i2c-4";
const int device_address = 0x50;
/* open the i2c device file */
int file = open(i2c_device, O_RDWR);
if (file < 0) {
printf("Failed opening %s\n", i2c_device);
return 1;
}
if (ioctl(file, I2C_SLAVE, device_address) < 0) {
printf("Failed addressing device at %02X\n", device_address);
close(file);
return 1;
}
int i = 0;
for (i = 0; i < NB_PAGES; i++) {
char buf[READ_SIZE] = {0};
if (read(file, buf, READ_SIZE) != READ_SIZE) {
printf("Failed reading\n");
close(file);
return 1;
}
dump_to_file(argv[1], buf, READ_SIZE);
}
close(file);
return 0;
}
By "almost" I mean that it dumps the full eeprom but the START depends on the last block read..
It's not always the same.
If I read 10 blocks. then run the program again I read the next ones and not the first 10.
How to set the starting address?
Update:
if I do:
i2cset -y 4 0x50 0x00 0x00
and the run the above code, it works.
so how can I put the equivalent of the i2cset command in the code?
Done!
It wasn't easy because I could not find documentations anywhere.. but I thought that since the eeprom is 32K, maybe it was "like" a 24c256. But even in that case I found nothing in userspace until I decided to go by instinct.
I studied i2cset source, understood what it did and put it in the code.
Here is the result, which dumps a full i2c 32k eprom from userspace.
Note a full backup and restore utility can be found here:
https://gist.github.com/Zibri/cf8ac0b311301aeeaa8910c7da824bff
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <linux/i2c-dev.h>
#define READ_SIZE (256)
#define NB_PAGES (128)
void dump_to_file(const char *output_file_path,
const uint8_t *buffer, const int buffer_length)
{
int output_file = open(output_file_path, O_RDWR|O_APPEND|O_CREAT);
if (output_file < 0) {
printf("Failed opening output file %s\n", output_file_path);
return;
}
write(output_file, buffer, buffer_length);
}
int main(int argc, char *argv[])
{
const char *i2c_device = "/dev/i2c-4";
const int device_address = 0x50;
int file = open(i2c_device, O_RDWR);
if (file < 0) {
printf("Failed opening %s\n", i2c_device);
return 1;
}
if (ioctl(file, I2C_SLAVE, device_address) < 0) {
printf("Failed addressing device at %02X\n", device_address);
close(file);
return 1;
}
int i = 0;
write(file,'\x00\x00',2); // ADDRESS
for (i = 0; i < NB_PAGES; i++) {
char buf[READ_SIZE] = {0};
if (read(file, buf, READ_SIZE) != READ_SIZE) {
printf("Failed reading\n");
close(file);
return 1;
}
dump_to_file(argv[1], buf, READ_SIZE);
}
close(file);
return 0;
}

NIOS II error: invalid suffix on integer constant

So I've been making an SD card music player on a DE2-155 board for a while. I've finally finished the hardware and have moved into coding in C to finish it up. However, before I can build the project I keep getting the error: "Invalid suffix "0b00100000" on integer constant."
Here is my C code:
#include <io.h>
#include <system.h>
#include "altera_up_avalon_audio_and_video_config.h"
#include "altera_up_avalon_audio.h"
#define SD_CARD_OFFSET_RXTX 0
#define SD_CARD_OFFSET_CMD 560
#define SD_CARD_OFFSET_CMD_ARG 556
#define SD_CARD_OFFSET_ASR 564
#define SD_CONNECTED 0x02
#define SD_COMPLETE 0x04
#define SD_BLOCK_SIZE 512
#define SD_CMD_READ 0x11
int main()
{
int *sd_asr = (int *)(ALTERA_UP_SD_CARD_AVALON_INTERFACE_0_BASE + SD_CARD_OFFSET_ASR);
short int sd_status;
int res;
int sector_count, byte_count;
unsigned int l_buff,r_buff;
alt_up_av_config_dev* cfg_dev;
alt_up_audio_dev* audio_dev;
/* Wait for SD-Card */
printf("Wait for SD-Card to be connected...\n");
do{
sd_status=(short int)IORD_16DIRECT(sd_asr,0);
}while((sd_status & SD_CONNECTED) == 0);
printf("SD-Card connected.\n");
/* Initialize CFG/Audio Device */
cfg_dev=alt_up_av_config_open_dev("/dev/audio_and_video_config_0");
if(cfg_dev == NULL){
printf("Config device not found.\n");
}else{
printf("Config device opened for configuration.\n");
}
printf("Resetting config device and peripherals...\n");
res = alt_up_av_config_reset(cfg_dev);
alt_up_av_config_write_audio_cfg_register(cfg_dev,0x08,0b00100000);
if(res == 0){
printf("Reset successful.\n");
}else{
printf("Reset failed.\n");
}
/* Play Music */
audio_dev = alt_up_audio_open_dev("/dev/audio_0");
if(audio_dev == NULL){
printf("Failed to open audio device.\n");
}else{
printf("Audio device opened.\n");
}
printf("Starting playback!\n");
sector_count=0;
while(1)
{
/* Read 512B sector from SD-Card */
IOWR_32DIRECT(ALTERA_UP_SD_CARD_AVALON_INTERFACE_0_BASE,SD_CARD_OFFSET_CMD_ARG,sector_count*512);
IOWR_16DIRECT(ALTERA_UP_SD_CARD_AVALON_INTERFACE_0_BASE,SD_CARD_OFFSET_CMD,SD_CMD_READ);
do{
sd_status=(short int)IORD_16DIRECT(ALTERA_UP_SD_CARD_AVALON_INTERFACE_0_BASE,SD_CARD_OFFSET_ASR);
}while((sd_status & SD_COMPLETE) != 0);
byte_count=0;
while(byte_count < 512){
l_buff = (unsigned int)IORD_16DIRECT(ALTERA_UP_SD_CARD_AVALON_INTERFACE_0_BASE,SD_CARD_OFFSET_RXTX+byte_count);
r_buff = (unsigned int)IORD_16DIRECT(ALTERA_UP_SD_CARD_AVALON_INTERFACE_0_BASE,SD_CARD_OFFSET_RXTX+(byte_count+2));
byte_count+=4;
while(alt_up_audio_write_fifo_space(audio_dev,ALT_UP_AUDIO_RIGHT) < 4){ asm("NOP"); }
alt_up_audio_write_fifo (audio_dev, &(r_buff), 1, ALT_UP_AUDIO_RIGHT);
alt_up_audio_write_fifo (audio_dev, &(l_buff), 1, ALT_UP_AUDIO_LEFT);
}
sector_count++;
}
return 0;
}
The error is on line
alt_up_av_config_write_audio_cfg_register(cfg_dev,0x08,0b00100000);
0b00100000 is an integer value. If an integer value starts with a 0, the next character must be either an x to declare the integer number as hexadecimal number, or it will be interpreted as octal number. An octal number can have only the digits 0 to 7.
0b00100000 is binary which is decimal 32 or hexadecimal 0x20.
See also Can I use a binary literal in C or C++?
A binary notation like 0b00100000 is supported only by GCC with enabled GCC extensions.

UART compare charts. Beaglebone

I have a problem trying to compare the uart input data (from a GPS) with '$' in order to detect a new package. I am sure that the problem is in how I manipulate the charRead variable. I tried one thousand of things, but probably because of my inexperience I have not figured out what it is the problem.
The code compiles and the data is coming all the time, but once I load the code into the beaglebone, it gets stacked but and it doesn't enter in the "if (charRead =='$')".
Thank you in advance!
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <time.h>
#include <iostream>
#include <termios.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <string.h>
#include <ctype.h>
#include <math.h>
#include <limits.h>
#include "Payload.h"
#define SLOTS "/sys/devices/bone_capemgr.9/slots"
#define CR 0x0d
#define SPACE 0x20
#define COMMA 0x2C
#define MAXSIZE 100
unsigned long time_data;
unsigned int button = 45;
int i,z =0, j=0, value;
int rx_length;
int main()
{
//uart4 configuration using termios
int fd;
//unsigned char *mess;
unsigned int value = 0;
gpio_export(button);
//Wait until the button is pushed
while (value != 1){
if (z==0){
printf("waiting\n");}
z++;
gpio_get_value(button, &value);}
//OPEN THE UART
//open uart4 for tx/rx, not controlling device
if((fd = open("/dev/ttyO4", O_RDONLY | O_NOCTTY|O_NONBLOCK)) < 0){
printf("Unable to open uart4 access.\n");
}
termios uart4;
cfsetospeed(&uart4, B9600); //Set the speed
//set attributes of uart4
uart4.c_iflag = 0;
uart4.c_oflag = 0;
uart4.c_lflag = 0;
tcsetattr(fd, TCSANOW, &uart4);
//----- CHECK FOR ANY RX BYTES -----
// Read up to 100 characters from the port if they are there
unsigned char stringRead[MAXSIZE];
unsigned char charRead;
do{
if (rx_length = read(fd, (void*)charRead, MAXSIZE)>0){
if (charRead =='$'){
i=0;
stringRead[i] = charRead; //Store in the first position of the char --> $
do {
rx_length = read(fd, (void*)charRead, MAXSIZE); //Read the next bit
if( (charRead != '\0') ) {
i++;
stringRead[i] = charRead; //write into stringRead
}
} while(charRead != 'CR'); //ASCII Carriage Return
stringRead[i+1] = charRead;
printf("%s", stringRead);
}}
if (rx_length==0){
//No data
}
gpio_get_value(button, &value);
}while (value!=0);
gpio_unexport(button);
close(fd);
return 0;
}
You're passing a cast of the variable value of charRead rather than a pointer to a memory location as the function read() expects void *.
read(fd, (void*)charRead, MAXSIZE)
You need to either read one character at a time:
read(fd, &charRead, 1)
Or change your reading logic to maximize amount read and data processing. I also recommend adding a bounds check on accessing stringRead.
// The following should handle the reading of a GPS NMEA message and display it
// I have not run the program, but compiling it was successful
// note:
// 1) the handling of the 'i' variable
// 2) the calls to reading the GPS input
// 3) the handling of error conditions
// 4) the simple logic flow
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <time.h>
//#include <iostream> // this is not C++ so this line not needed
#include <termios.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <string.h>
#include <ctype.h>
#include <math.h>
#include <limits.h>
#include "Payload.h"
// #define SLOTS "/sys/devices/bone_capemgr.9/slots" // not used, raises compiler warning
#define CR (0x0D)
// #define SPACE (0x20) // not used, raises compiler warning
// #define COMMA (0x2C) // not used, raises compiler warning
#define MAXSIZE (100)
#define BUTTON_PORT (45)
// unsigned long time_data; // not used, raises compiler warning
// int j=0; // not used, raises compiler warning
// int value = 0; // not used, raises compiler warning about variable masking
int main()
{
int i;
int z = 0; // flag used to control execution flow
int rx_length; // return status value from read()
//uart4 configuration using termios
int fd; // file descriptor number
//unsigned char *mess; // not used, raises compiler warning
unsigned int value = 0;
gpio_export(BUTTON_PORT);
//Wait until the button is pushed
// burn mass CPU cycles, while waiting
while (0 == value)
{
if (z==0)
{
printf("waiting\n");
z++; // to stop re-entry to this 'if' block
}
// suggest using nsleep() to free up CPU
gpio_get_value(BUTTON_PORT, &value);
} // end while
//open uart4 for rx
if((fd = open("/dev/ttyO4", O_RDONLY | O_NOCTTY|O_NONBLOCK)) < 0)
{
perror("open failed for /dev/tty04");
exit(1);
}
// implied else, open successful
termios uart4;
cfsetospeed(&uart4, B9600); //Set the speed to match the GPS output
//set attributes of uart4
// Note: probably better to read the current termois values
// then modify them to the desired states
uart4.c_iflag = 0;
uart4.c_oflag = 0;
uart4.c_lflag = 0;
tcsetattr(fd, TCSANOW, &uart4);
//----- CHECK FOR ANY RX BYTES -----
// Read up to 100 characters from the port if they are there
unsigned char stringRead[MAXSIZE]; // will contain a GPS NMEA message
unsigned char charRead; // input buffer
do{
while(1)
{
rx_length = read(fd, &charRead, 1);
if( 0 == rx_length )
{ // this will execute a lot since fd set to non-blocking
; // do nothing, while hogging CPU cycles
// suggest using nsleep() to free CPU
}
else if( 0 > rx_length )
{
perror( "read failed" );
exit(1);
}
else if (charRead =='$')
{
stringRead[0] = charRead; //Store first char of NMEA GPS message
i=1; // index for second char of NMEA message from GPS
}
else
{
stringRead[i] = charRead; //Store char
i++; // index for next char into stringRead buffer
if( MAXSIZE <= i )
{ // then overrun input buffer
perror( "read- overrun input buffer, GPS message too long");
exit(2);
}
if( CR == charRead ) //ASCII Carriage Return - end of message
{ // then, got complete message
break; // exit read loop, so can process message
}
} // end if
} // end while
stringRead[i] = '\0'; // terminate string so it can be printed
printf("%s", stringRead);
// get button state via BUTTON_PORT(45)
gpio_get_value(BUTTON_PORT, &value);
} while (value!=0); // then read next gps message
gpio_unexport(BUTTON_PORT);
close(fd);
return 0;
}

Serial I/O in C with termios: unreliable output capitalization

I have a very small C program which sends and receives newline-terminated ASCII strings to and from a serial device. It's plugged into my computer with a USB adapter, on /dev/ttyUSB0.
Most of the time it sends the commands just find, but occasionally it will capitalize all the lower-case letters to upper-case. It leaves all special characters alone.
The string I am sending is /home\n. About 1 out of every five times I run the program (by simply running ./a.out without recompiling), the sent message understood by the device is /HOME\n.
Here is my source code:
#include <stdio.h>
#include <stdlib.h>
#include "zserial.h"
int main() {
char buf[256];
int fd = connect("/dev/ttyUSB0");
char *cmd = "/home\n";
send(fd, cmd);
receive(fd, buf, 256);
puts(buf);
exit(0);
}
And zserial.c:
#include <fcntl.h>
#include <termios.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "zserial.h"
int send(int fd, char *buf) {
int len = strlen(buf);
int nb = write(fd, buf, len);
if (len != nb || nb < 1)
perror("Error: wrote no bytes!");
tcdrain(fd);
return nb;
}
int receive(int fd, char *dst, int nbytes) {
int i;
char c;
for(i = 0; i < nbytes;) {
int r = read(fd, &c, 1);
/* printf("Read %d bytes\n", r); */
if (r > 0) {
dst[i++] = c;
if (c == '\n') break;
}
}
dst[i] = 0; /* null-terminate the string */
return i;
}
int connect(char *portname) {
int fd;
struct termios tio;
fd = open(portname, O_RDWR | O_NOCTTY | O_NONBLOCK);
tio.c_cflag = CS8|CREAD|CLOCAL;
if ((cfsetospeed(&tio, B115200) & cfsetispeed(&tio, B115200)) < 0) {
perror("invalid baud rate");
exit(-1);
}
tcsetattr(fd, TCSANOW, &tio);
return fd;
}
What am I doing wrong? Is there some termios flag which modifies the output on a serial port?
c_oflag & OLCUC turns on the mapping of lowercase to uppercase on output. Since you never initialized tio, it's not surprising you got some random flags set.
You have two choices:
tcgetattr the current settings into a termios struct to initialize it, then modify the ones you're interested in, then write them back with tcsetattr
initialize all the termios fields to known values, not just c_cflag and the speed fields.

Input within a time limit in Standard C

I'm currently doing my assignment and it's compulsory to use C-Free 5.0. Just need your help to solve this piece of puzzle. I want to implement a time limit for the user to input an answer before it expires. I've tried this code but it got block at scanf() function. Is there any other method like an unblocking input or something. I've tried to implement '#include <sys/select.h>' but this program doesn't have that library.
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <stdlib.h>
int main()
{
char st[10];
printf ("Please enter a line of text : ");
time_t end = time(0) + 5; //5 seconds time limit.
while(time(0) < end)
{
scanf("%s", &st);
if(st != NULL)
{
printf ("Thank you, you entered >%s<\n", st);
exit(0);
}
}
main();
}
Here is an example program that shows how you can use O_NONBLOCK flag on a stdin file descriptor.
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#define INPUT_LEN 10
int main()
{
printf ("Please enter a line of text : ");
fflush(stdout);
time_t end = time(0) + 5; //5 seconds time limit.
int flags = fcntl(STDIN_FILENO, F_GETFL, 0);
fcntl(STDIN_FILENO, F_SETFL, flags | O_NONBLOCK);
char answer[INPUT_LEN];
int pos = 0;
while(time(0) < end)
{
int c = getchar();
/* 10 is new line */
if (c != EOF && c != 10 && pos < INPUT_LEN - 1)
answer[pos++] = c;
/* if new line entered we are ready */
if (c == 10)
break;
}
answer[pos] = '\0';
if(pos > 0)
printf("%s\n", answer);
else
puts("\nSorry, I got tired waiting for your input. Good bye!");
}
Since you have fcntl.h try setting stdin to non-blocking. It's not pretty (active waiting), but if you do not have select then this is the easyest way to go:
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>
int main()
{
// get stdin flags
int flags = fcntl(0, F_GETFL, 0);
if (flags == -1) {
// fcntl unsupported
perror("fcntl");
return -1;
}
// set stdin to non-blocking
flags |= O_NONBLOCK;
if(fcntl(0, F_SETFL, flags) == -1) {
// fcntl unsupported
perror("fcntl");
return -1;
}
char st[1024] = {0}; // initialize the first character in the buffer, this is generally good practice
printf ("Please enter a line of text : ");
time_t end = time(0) + 5; //5 seconds time limit.
// while
while(time(0) < end // not timed out
&& scanf("%s", st) < 1 // not read a word
&& errno == EAGAIN); // no error, but would block
if (st[0]) // if the buffer contains something
printf ("Thank you, you entered >%s<\n", st);
return 0;
}
A remark to your code: if (st != NULL) will always be satisfied since st is a stack pointer.

Resources