Initialising LCD eadip203-6 using functions over Beaglebone Black SPI - c

I am trying to write down the functions for the LCD initialisation with the LCD screen eadip203-6 using SPI on beaglebone black. I am facing some problems as I am trying to execute the functions, initially the screen gets stuck, then if I comment the above functions and see what happens the cursor still blinks. I am trying to do this from page number 29,30 and 33,34,35,36,37,38,39,40 of the data sheet. I have not written all the 16 functions. But written a few of the starting ones.Now as soon as I execute the last two functions from the above code the screen goes blank. Can you please tell me where am I going wrong in this? Also can you please tell me about the CGRAM,SEGRAM, DDRAM and the busy flag.
#include <stdint.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/types.h>
#include <linux/spi/spidev.h>
#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
static void transfer(int fd, uint16_t* tx, uint8_t cs);
void init_display(int fd);
void clear_display_func(int fd);
void return_home_func(int fd);
void power_mode_func(int fd);
void entry_mode_set_func(int fd);
void display_on_off_func(int fd);
void extended_function_set_func(int fd);
void cursor_display_shift_bias_func(int fd);
static void pabort(const char *s)
{
perror(s);
abort();
}
static const char *device = "/dev/spidev2.1";
static uint8_t mode=3;
static uint8_t bits = 8;
static uint32_t speed = 40000;
static uint16_t delay;
void clear_display_func(int fd)
{
int ret;
uint16_t clear_display[]={0xF8,0x80,0x00};
for(ret=0; ret<3; ret++)
{
transfer(fd,&clear_display[ret],0);
usleep(2000);
}
}
void return_home_func(int fd)
{
int ret;
uint16_t return_home[]={0xF8,0x40,0x00};
for(ret=0; ret<3; ret++)
{
transfer(fd,&return_home[ret],0);
usleep(2000);
}
}
void power_mode_func(int fd)
{
int ret;
uint16_t power_mode[]={0xF8,0xC0,0x00};
for(ret=0; ret<3; ret++)
{
transfer(fd,&power_mode[ret],0);
usleep(2000);
}
}
void entry_mode_set_func(int fd)
{
int ret;
uint16_t entry_mode_set[]={0xF8,0xE0,0x00,
0xF8,0x60,0x00};
for(ret=0; ret<6; ret++)
{
transfer(fd,&entry_mode_set[ret],0);
usleep(2000);
}
}
void display_on_off_func(int fd)
{
int ret;
uint16_t display_on_off[]={0xF8,0xF0,0x00};
for(ret=0; ret<3; ret++)
{
transfer(fd,&display_on_off[ret],0);
usleep(2000);
}
}
void extended_function_set_func(int fd)
{
int ret;
uint16_t extended_function_set[]={0xF8,0xD0,0x00};
for(ret=0; ret<3; ret++)
{
transfer(fd,&extended_function_set[ret],0);
usleep(2000);
}
}
void cursor_display_shift_bias_func(int fd)
{
int ret;
uint16_t cursor_display_shift_bias[]={0xF8,0x50,0x80};
for(ret=0; ret<3; ret++)
{
transfer(fd,&cursor_display_shift_bias[ret],0);
usleep(2000);
}
}
static void transfer(int fd, uint16_t* tx, uint8_t cs){
int ret;
uint16_t rx[ARRAY_SIZE(tx)] = {0, };
struct spi_ioc_transfer tr = {
.tx_buf = (unsigned long)tx,
.rx_buf = 0,
.len = 1,
.delay_usecs = delay,
.speed_hz = speed,
.bits_per_word = bits,
.cs_change=cs,
};
printf("%u", cs);
ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
if (ret < 1)
pabort("can't send spi message");
puts("");
}
static void print_usage(const char *prog)
{
printf("Usage: %s [-DsbdlHOLC3]\n", prog);
puts(" -D --device device to use (default /dev/spidev1.1)\n"
" -s --speed max speed (Hz)\n"
" -d --delay delay (usec)\n"
" -b --bpw bits per word \n"
" -l --loop loopback\n"
" -H --cpha clock phase\n"
" -O --cpol clock polarity\n"
" -L --lsb least significant bit first\n"
" -C --cs-high chip select active high\n"
" -3 --3wire SI/SO signals shared\n");
exit(1);
}
static void parse_opts(int argc, char *argv[])
{
while (1) {
static const struct option lopts[] = {
{ "device", 1, 0, 'D' },
{ "speed", 1, 0, 's' },
{ "delay", 1, 0, 'd' },
{ "bpw", 1, 0, 'b' },
{ "loop", 0, 0, 'l' },
{ "cpha", 0, 0, 'H' },
{ "cpol", 0, 0, 'O' },
{ "lsb", 0, 0, 'L' },
{ "cs-high", 0, 0, 'C' },
{ "3wire", 0, 0, '3' },
{ "no-cs", 0, 0, 'N' },
{ "ready", 0, 0, 'R' },
{ NULL, 0, 0, 0 },
};
int c;
c = getopt_long(argc, argv, "D:s:d:b:lHOLC3NR", lopts,
NULL);
if (c == -1)
break;
switch (c) {
case 'D':
device = optarg;
break;
case 's':
speed = atoi(optarg);
break;
case 'd':
delay = atoi(optarg);
break;
case 'b':
bits = atoi(optarg);
break;
case 'l':
mode |= SPI_LOOP;
break;
case 'H':
mode |= SPI_CPHA;
break;
case 'O':
mode |= SPI_CPOL;
break;
case 'L':
mode |= SPI_LSB_FIRST;
break;
case 'C':
mode |= SPI_CS_HIGH;
break;
case '3':
mode |= SPI_3WIRE;
break;
case 'N':
mode |= SPI_NO_CS;
break;
case 'R':
mode |= SPI_READY;
break;
default:
print_usage(argv[0]);
break;
}
}
}
int main(int argc, char *argv[])
{
int ret = 0;
int fd;
parse_opts(argc, argv);
fd = open(device, O_RDWR);
if (fd < 0)
pabort("can't open device");
/*
* spi mode
*/
ret = ioctl(fd, SPI_IOC_WR_MODE, &mode);
if (ret == -1)
pabort("can't set spi mode");
ret = ioctl(fd, SPI_IOC_RD_MODE, &mode);
if (ret == -1)
pabort("can't get spi mode");
/*
* bits per word
*/
ret = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits);
if (ret == -1)
pabort("can't set bits per word");
ret = ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &bits);
if (ret == -1)
pabort("can't get bits per word");
/*
* max speed hz
*/
ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed);
if (ret == -1)
pabort("can't set max speed hz");
ret = ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed);
if (ret == -1)
pabort("can't get max speed hz");
printf("spi mode: %d\n", mode);
printf("bits per word: %d\n", bits);
printf("max speed: %d Hz (%d KHz)\n", speed, speed/1000);
init_display(fd);
usleep(20000);
clear_display_func(fd);
usleep(20000);
return_home_func(fd);
usleep(20000);
power_mode_func(fd);
usleep(20000);
entry_mode_set_func(fd);
usleep(20000);
display_on_off_func(fd);
usleep(20000);
extended_function_set(fd);
usleep(20000);
cursor_display_shift_bias_func(int fd);
usleep(20000);
close(fd);
return ret;
}

Related

Concurrency thread read write different UART linux C Programming

I try to read and write data by two different UART.
I create two thread to comunicate with theese UARTs. Every thread use diffent UART
Some Time, when I write data to UART, write function return with all byte whiuout error, but elettrical port not send all byte.
If I comment second thread, I haven't this error.
Why? Somebody know the problem?
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <errno.h>
#include <fcntl.h>
#include <string.h>
#include <termios.h>
#include <unistd.h>
#include <stdint.h>
#include "log4c.h"
#include <pthread.h>
pthread_t threadId[2]; /*!< Array di pthread_t. In presenza di micro, vengono avviati 2 thread, uno per ogni micro per la generazione del crc*/
/** \struct parameters
* \brief Struttura contenente i parametri scambiati con il thread che calcola il crc
*/
struct parameters {
uint8_t* Buffer; /*!< Puntatore al buffer contenente i dati di cui calcolare il crc */
uint32_t length; /*!< Lunghezza in byte del buffer contenente i dati */
uint32_t crc; /*!< Contiene il valore del crc calcolato dal micro */
uint8_t microNumber; /*!< Valore numerico che identifica il micro: 1->micro1, 2->micro2 */
};
int fdMicroFirst; /*!<Memorizza l'identificativo numerico del microcontrollore 1 */
int fdMicroSecond; /*!<Memorizza l'identificativo numerico del microcontrollore 2 */
/*
*
*/
int setInterfaceAttribs(int speed, int parity, int fd) {
struct termios tty;
if (tcgetattr(fd, &tty) != 0) {
printf("error %d from tcgetattr", errno);
return -1;
}
cfsetospeed(&tty, speed);
cfsetispeed(&tty, speed);
tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8; // 8-bit chars
// disable IGNBRK for mismatched speed tests; otherwise receive break
// as \000 chars
tty.c_iflag &= ~IGNBRK; // disable break processing
tty.c_lflag = 0; // no signaling chars, no echo,
// no canonical processing
tty.c_oflag = 0; // no remapping, no delays
tty.c_iflag &= ~(IXON | IXOFF | IXANY | INLCR | ICRNL); // shut off xon/xoff ctrl
//INLCR | ICRNL in questo modo viene disabilitata la conversione da Carriege return (CR) a new line(NL) e viceversa.
//Se non vengono disabilitate queste due configurazioni 0x0d viene letto come 0x0a
tty.c_cflag |= (CLOCAL | CREAD); // ignore modem controls,
// enable reading
tty.c_cflag &= ~(PARENB | PARODD); // shut off parity
tty.c_cflag |= parity;
tty.c_cflag &= ~CSTOPB;
tty.c_cflag &= ~CRTSCTS;
if (tcsetattr(fd, TCSANOW, &tty) != 0) {
printf("error %d from tcsetattr", errno);
return -1;
}
return 0;
}
void setBlocking(int should_block, int fd) {
struct termios tty;
memset(&tty, 0, sizeof tty);
if (tcgetattr(fd, &tty) != 0) {
printf("error %d from tggetattr", errno);
return;
}
tty.c_cc[VMIN] = should_block ? 4 : 0;
tty.c_cc[VTIME] = 2.5; // 0.5 seconds read timeout era impostato a 5
if (tcsetattr(fd, TCSANOW, &tty) != 0)
printf("error %d setting term attributes", errno);
}
int openSerialCommunication(char *portname, int speed, int microNumber) {
int retVal = -1;
int fd = open(portname, O_RDWR | O_NOCTTY | O_SYNC);
if (fd < 0) {
printf("error %d opening %s: %s", errno, portname, strerror(errno));
return -1;
}
if (speed == 115200) {
speed = B115200;
} else if (speed == 460800) {
speed = B460800;
} else if (speed == 921600) {
speed = B921600;
}
if (microNumber == 1) {
fdMicroFirst = fd;
//retVal = setInterfaceAttribs(B115200, 0, fdMicroFirst); // set speed to 115,200 bps, 8n1 (no parity)
retVal = setInterfaceAttribs(speed, 0, fdMicroFirst); // set speed to 115,200 bps, 8n1 (no parity)
//retVal = setInterfaceAttribs(B460800, 0, fdMicroFirst); // set speed to 115,200 bps, 8n1 (no parity)
setBlocking(0, fdMicroFirst); // set no blocking
if (tcflush(fdMicroFirst, TCOFLUSH) != 0) {
printf("Errore flush Output Buffer Micro %d\n", microNumber);
}
} else if (microNumber == 2) {
fdMicroSecond = fd;
//retVal = setInterfaceAttribs(B115200, 0, fdMicroSecond); // set speed to 115,200 bps, 8n1 (no parity)
retVal = setInterfaceAttribs(speed, 0, fdMicroSecond); // set speed to 115,200 bps, 8n1 (no parity)
setBlocking(0, fdMicroSecond); // set no blocking
if (tcflush(fdMicroSecond, TCOFLUSH) != 0) {
printf("Errore flush Output Buffer Micro %d\n", microNumber);
}
}
return retVal;
}
void closeSerialCommunication() {
if (fdMicroFirst != -1) {
close(fdMicroFirst);
}
if (fdMicroSecond != -1) {
close(fdMicroSecond);
}
}
uint32_t calculateCrc(uint8_t* buffer, uint16_t bufferLengthCrc, int microNumber) {
uint8_t write_buffer[1100];
uint32_t crc = 0;
int fdMicro = -1;
uint8_t readBuffer [4] = {0x00, 0x00, 0x00, 0x00};
int numB = 0;
int n = 0;
int nTemp;
uint8_t crcBuffer [4] = {0x00, 0x00, 0x00, 0x00};
int counter = 0;
struct timespec startTime, stopTime;
uint16_t dimBufferTosend = 0;
uint16_t numnByteSent = 0;
if (microNumber == 1) {
fdMicro = fdMicroFirst;
} else if (microNumber == 2) {
fdMicro = fdMicroSecond;
}
//I primi due byte che vengono inviati alla seriale rappresentano il numero di byte
//che costituiscono il dato inviato
if (bufferLengthCrc <= 0xFFFF) {
write_buffer[0] = (bufferLengthCrc & 0xFF00) >> 8;
write_buffer[1] = (bufferLengthCrc & 0x00FF);
//printf("UART Write Buffer: %x %x\n",write_buffer[0],write_buffer[1]);
for (int i = 0; i < bufferLengthCrc; i++) {
write_buffer[i + 2] = buffer[i];
//printf("Write Buffer: %x ", write_buffer[i + 2]);
/*
printf("Write Buffer: %x \n",write_buffer[i + 2]);
*/
}
printf("Flushing Micro %d with fd: %d\n", microNumber, fdMicro);
if (tcflush(fdMicro, TCOFLUSH) != 0) {
printf("Errore flush Output Buffer Micro %d\n", microNumber);
}
dimBufferTosend = bufferLengthCrc + 2;
numnByteSent = 0;
numB = 1;
while (numnByteSent < dimBufferTosend && numB > 0) {
numB = write(fdMicro, write_buffer + numnByteSent, dimBufferTosend - numnByteSent);
numnByteSent = numnByteSent + numB;
printf("Byte scritti su Micro %d:%d\n", microNumber, numnByteSent);
printf( "Byte rimanenti da scrivere su Micro %d:%d\n", microNumber, dimBufferTosend - numnByteSent);
}
if (numnByteSent >= dimBufferTosend) {
//printf("UART Buffer: \n");
//clock_gettime(CLOCK_REALTIME, &startTime);
while (n < 4) {
nTemp = read(fdMicro, readBuffer, sizeof readBuffer); // read up to 100 characters if ready to read
//printf("ntemp:%d ",nTemp);
if (nTemp != 0 && nTemp != -1) {
int j = 0;
for (int k = n; k < n + nTemp; k++) {
crcBuffer[k] = readBuffer[j];
printf(" 0x%x 0x%x ", crcBuffer[k], readBuffer[j]);
j++;
}
printf("UART Buffer Response Micro %d: \n", microNumber);
n = n + nTemp;
} else {
if (counter == 3) {
n = 4;
for (int i = 0; i < bufferLengthCrc + 2; i++) {
//printf("Write Buffer: %x ", write_buffer[i]);
}
printf("CRC Ricevuto: 0x%x 0x%x 0x%x 0x%x\n", crcBuffer[0], crcBuffer[1], crcBuffer[2], crcBuffer[3]);
printf( "Risposta CRC da MICRO %d non pervenuta\n", microNumber);
while (1) {
usleep(1000);
}
} else {
counter = counter + 1;
}
}
}
}
printf("CRC Ricevuto: 0x%x 0x%x 0x%x 0x%x\n", crcBuffer[0], crcBuffer[1], crcBuffer[2], crcBuffer[3]);
crc = (crcBuffer[0] << 24)+(crcBuffer[1] << 16)+(crcBuffer[2] << 8)+(crcBuffer[3]);
}
return crc;
}
///Thread calcolo CRC
void *
crcCalcThread(void *_args) {
printf("crccalcthread\n");
/* Cast the arguments to the usable struct type */
struct parameters *args = (struct parameters *) _args;
/* Place the result into the struct itself (on the heap) */
args->crc = calculateCrc(args->Buffer, args->length, args->microNumber);
printf("after crccalcthread\n");
return 0;
//pthread_exit(NULL);
}
int main(int argc, char** argv) {
uint8_t Buffer[1100];
uint32_t crc32pol1;
uint32_t crc32pol2;
//int retValInitMutex=pthread_mutex_init(&(lockWrite), NULL);
openSerialCommunication("/dev/ttySTM4",115200,1);
openSerialCommunication("/dev/ttySTM3",115200,2);
while(1)
{
for (int i = 0; i < 1024; i++) {
Buffer[i] = 0x03;
//printf("Write Buffer: %x ", write_buffer[i + 2]);
}
struct parameters *argsFirstMicro = calloc(sizeof (struct parameters), 1);
argsFirstMicro->Buffer = Buffer;
argsFirstMicro->length = 1024;
argsFirstMicro->microNumber = 1;
int err = pthread_create(&(threadId[0]), NULL, &crcCalcThread, argsFirstMicro);
if (err != 0)
printf("can't create thread :[%s]\n", strerror(err));
else
printf("crcCalcThread created successfully!\n");
//MICRO 2
/*crc32pol2 = crc32(Buffer, (packetLength + slPDU_SAFETY_CODE_NUM_BYTE+ paddingNum), CRC32_POLY_CH2_INV);
log4c_category_log(slcat, LOG4C_PRIORITY_DEBUG, "CRC2 NO MICRO:%x\n", crc32pol2);
printf("CRC2 NO MICRO:%x", crc32pol2);*/
struct parameters *argsSecondMicro = calloc(sizeof (struct parameters), 1);
argsSecondMicro->Buffer = Buffer;
argsSecondMicro->length = 1024;
argsSecondMicro->microNumber = 2;
err = pthread_create(&(threadId[1]), NULL, &crcCalcThread, argsSecondMicro);
if (err != 0)
printf( "can't create thread :[%s]\n", strerror(err));
else
printf("crcCalcThread created successfully!\n");
pthread_join(threadId[0], NULL);
pthread_join(threadId[1], NULL);
crc32pol1 = argsFirstMicro->crc;
/*
Clean up the struct instance
*/
free(argsFirstMicro);
argsFirstMicro = NULL;
crc32pol2 = argsSecondMicro->crc;
// Clean up the struct instance
free(argsSecondMicro);
argsSecondMicro = NULL;
usleep(4);
}
return (EXIT_SUCCESS);
}

Connecting a program and Arduino with Serial-port

I'm using Ubuntu 16 (although i have the same problem on Debian) Arduino Mega 2560, 2 versions of Arduino IDE: 2:1.0.5+dfsg2-4.1 and 1.8.9.
I'm working on a connecting a C program with Arduino via COM-port.
For example, I have following code; a PC program sends some text to Arduino, while Arduino receives and prints it.
pc.c:
#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <termios.h>
int openPort(char port_name[], speed_t speed)
{
int F_ID = open(port_name, O_RDWR | O_NOCTTY);
fcntl(F_ID, F_SETFL, 0);
//printf("%s\n", port_name);
if(F_ID == -1)
{
return -1;
}
struct termios options;
tcgetattr(F_ID, &options);
cfsetispeed(&options, speed);
cfsetospeed(&options, speed);
options.c_cc[VTIME] = 20;
options.c_cc[VMIN] = 0;
options.c_cflag &= ~PARENB;
options.c_cflag &= ~CSTOPB;
options.c_cflag &= ~CSIZE;
options.c_cflag |= CS8;
options.c_lflag = 0;
options.c_oflag &= ~OPOST;
tcsetattr(F_ID, TCSANOW, &options);
return F_ID;
}
void closePort(int id)
{
close(id);
return;
}
int sendData(int id, unsigned char* buf, int len)
{
int n = write(id, buf, len);
if(n == -1)
{
char *errmsg = strerror(errno);
printf("%s\n",errmsg);
}
return n;
}
int main(int argc, char * argv[])
{
int port=openPort("/dev/ttyUSB0", B9600);
if ( (port) == -1){
//char *errmsg = strerror(errno);
printf("Cannot open port: %s\n",strerror(errno));
return -1;
}
sendData(port, "Hello, Arduino!*", 16);
closePort(port);
return 0;
}
ard.ino:
int stage = 0;
String recv;
char* line;
char* get_line(void)
{ // '*' is a terminal character
if (Serial.available() > 0)
{
char c = Serial.read();
if (c=='*')
{
char* res = (char*)malloc((recv.length()+1)*sizeof(char));
recv.toCharArray(res, recv.length()+1);
stage=1;
recv="";
return res;
}
else { recv += c; }
} // if (Serial.available() > 0)
}
void setup()
{
Serial.begin(9600);
}
void loop()
{
if (stage==0)
{
line = get_line();
}
else
{
Serial.print("Got line: ");
Serial.println(line);
stage = 0;
}
}
To check, if my program works fine, I'm using Port Monitor in the IDE.
I have following problem:
I prefer to use Arduino IDE 1.8.9, but when I open Port Monitor and run my PC program - nothing works, PC-prog can't access the port and send information (it says Bad file descriptor);
while with Arduino 2:1.0.5+dfsg2-4.1 everything works fine and i can see on Port Monitor:
Got line: Hello, Arduino!
So I'm asking, what I have to do with Arduino IDE 1.8.9 parameters or with /dev/ttyUSB* for it to work fine with each other?

How can I use a loopback device (or something similar) with epoll?

I am writing a small library module which accesses the UART and uses epoll to react on incoming data. It works fine with the tty device, however, I want to write test cases for this module. When I open a loop device (/dev/loop*) instead of a tty, epoll_ctl fails with EPERM. The Manual states:
EPERM: fd does not support epoll.
So the question is: Is there any kind of loopback device which could be used with epoll?
Here's a gist with my example code: https://gist.github.com/0815fox/9ce9f19648ce2dc9b23b37dbbb9adab4
#include <errno.h>
#include <fcntl.h>
#include <string.h>
#include <termios.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/epoll.h>
#include <linux/loop.h>
#include <sys/ioctl.h>
#include <pthread.h>
static int getFreeLoopDevice(const char * backingfileName) {
int loopctlfd, loopfd, backingfile;
long devnr;
char loopname[4096];
loopctlfd = open("/dev/loop-control", O_RDWR);
devnr = ioctl(loopctlfd, LOOP_CTL_GET_FREE);
close(loopctlfd);
return devnr;
sprintf(loopname, "/dev/loop%ld", devnr);
loopfd = open(loopname, O_RDWR);
backingfile = open(backingfileName, O_RDWR);
ioctl(loopfd, LOOP_SET_FD, backingfile);
return loopfd;
}
static int set_interface_attribs (int fd, int speed, int parity) {
struct termios tty;
memset (&tty, 0, sizeof tty);
if (tcgetattr (fd, &tty) != 0) {
fprintf (stderr, "error %d from tcgetattr", errno);
return -1;
}
cfsetospeed (&tty, speed);
cfsetispeed (&tty, speed);
tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8; // 8-bit chars
// disable IGNBRK for mismatched speed tests; otherwise receive break
// as \000 chars
tty.c_iflag &= ~IGNBRK; // disable break processing
tty.c_lflag = 0; // no signaling chars, no echo,
// no canonical processing
tty.c_oflag = 0; // no remapping, no delays
tty.c_cc[VMIN] = 0; // read doesn't block
tty.c_cc[VTIME] = 5; // 0.5 seconds read timeout
tty.c_iflag &= ~(IXON | IXOFF | IXANY); // shut off xon/xoff ctrl
tty.c_cflag |= (CLOCAL | CREAD);// ignore modem controls,
// enable reading
tty.c_cflag &= ~(PARENB | PARODD); // shut off parity
tty.c_cflag |= parity;
tty.c_cflag &= ~CSTOPB;
tty.c_cflag &= ~CRTSCTS;
if (tcsetattr (fd, TCSANOW, &tty) != 0) {
fprintf (stderr, "error %d from tcsetattr", errno);
return -1;
}
return 0;
}
void set_blocking (int fd, int should_block) {
struct termios tty;
memset (&tty, 0, sizeof tty);
if (tcgetattr (fd, &tty) != 0)
{
fprintf (stderr, "error %d from tggetattr", errno);
return;
}
tty.c_cc[VMIN] = should_block ? 1 : 0;
tty.c_cc[VTIME] = 5; // 0.5 seconds read timeout
if (tcsetattr (fd, TCSANOW, &tty) != 0)
fprintf (stderr, "error %d setting term attributes", errno);
}
static void * uart_thread(void * handle) {
const int uartHandle = *(int*)handle;
char buffer[100];
// the epoll stuff:
const int ePollFileDescriptor = epoll_create(1);
struct epoll_event ePollEvent;
ePollEvent.events = EPOLLIN;
ePollEvent.data.fd = uartHandle;
const int epoll_ctl_result = epoll_ctl(ePollFileDescriptor, EPOLL_CTL_ADD, uartHandle, &ePollEvent);
if (epoll_ctl_result) perror("epoll_ctl\n");
for (;;) {
static struct epoll_event events[1] __attribute__((aligned(8)));
const int eventCount = epoll_wait(ePollFileDescriptor, events, 1, -1);
if (eventCount < 0) {
perror("epoll_wait\n");
} else {
const int bytesRead = read(uartHandle, buffer, 99);
if (bytesRead >= 0) buffer[bytesRead] = 0;
else buffer[0] = 0;
fprintf(stderr, "Buffer: %s\nBytesread:%d\n", buffer, bytesRead);
}
}
}
int main (void) {
// working:
// char *portname = "/dev/ttyUSB0";
// const int uartHandle = open (portname, O_RDWR | O_NOCTTY | O_SYNC);
// not working:
const int uartHandle = getFreeLoopDevice("/tmp/my-loop-back");
if (uartHandle < 0) {
fprintf (stderr, "error %d opening: %s\n", errno, strerror (errno));
return errno;
}
set_interface_attribs (uartHandle, B115200, 0); // set speed to 115,200 bps, 8n1 (no parity)
set_blocking (uartHandle, 0); // set no blocking
// the pthread stuff:
pthread_t threadHandle;
const int pthread_create_result = pthread_create( &threadHandle, NULL, uart_thread, (void *) &uartHandle);
while (1) {
fprintf(stderr, "writing to uart\n");
write(uartHandle, "hello!\n", 7);
sleep(10);
}
}

Raspberry Pi SPI Connection: transition diagram malfunctioning

I am working with the raspberry pi and atmega 32 to use and learn SPI. it should follow a transition diagram but somewhere in the atmega it goes wrong, I don't know where it is going wrong.
this is the raspberry code
#include <wiringPi.h>
#include <stdio.h>
#include <wiringPiSPI.h>
#define SELECTADC 6
#define READY 8
#define GIVEADC 32
#define NOTREADY 0x10
#define DUMMY 0x55
#define ACK 10
#define IDLE 1
#define POLL 2
#define ADCSTART 3
#define ADCSTATE 4
#define ADCRESULT 5
main() {
int tellerPoll=0;
int teller=0;
int adcStatusTeller=0;
int status=0;
unsigned char data[4];
wiringPiSetup();
int kanaal = 0;
int adc;
int adcHigh=0;
int error=0;
if( wiringPiSPISetup (0, 500000)==-1)
{
printf("Could not initialise SPI\n");
status=0;
return;
} else {
status = IDLE;
printf("succesful initialised\n");
}
for(;;)
{
delay(20);
//wiringPiSPIDataRW(0,data,1);
switch(status){
case 0 :
exit(0);
case IDLE :
teller +=1;
if((teller % 2 == 1)&&1){
data[0] = POLL;
wiringPiSPIDataRW(0,data,1);
status = POLL;
//teller=0;
printf("Poll\n");
}
else if ((teller % 2 == 0)&&1){
status = ADCSTART;
}
break;
case POLL :
data[0] = DUMMY;
wiringPiSPIDataRW(0,data,1);
printf("Poll result: %x\n", data[0]);
if(data[0]==ACK){
status=IDLE;
printf("Poll succesfull\n");
tellerPoll=0;
}
else{
tellerPoll+=1;
if(tellerPoll>20){
status=0;
printf("No device found\n");
tellerPoll=0;
}
}
break;
case ADCSTART :
data[0]=ADCSTART;
wiringPiSPIDataRW(0,data,1);
status = ADCSTATE;
printf("ADCSTART\n");
break;
case ADCSTATE :
// printf("ADCSTATE\n");
data[0]=ADCSTATE;
wiringPiSPIDataRW(0,data,1);
//printf("%x\n",data[0]);
if(data[0]==READY){
status=ADCRESULT;
printf("Ready\n");
break;
}
else if(data[0]==NOTREADY){
printf("NOTREADY\n");
status=ADCSTATE;
adcStatusTeller+=1;
if(adcStatusTeller==100){
status=IDLE;
adcStatusTeller=0;
printf("no ADC result\n");
}
}
else{
adcStatusTeller+=1;
status =ADCSTATE;
printf("Weird result: %x\n", data[0]);
if (adcStatusTeller==100){
status=IDLE;
adcStatusTeller=0;
printf("no Results: %x \n", data[0]);
}
}
break;
case ADCRESULT :
data[0]=GIVEADC;
wiringPiSPIDataRW(0,data,1);
data[0]=DUMMY;
wiringPiSPIDataRW(0,data,1);
adc = data[0];
delay(10);
data[0]=DUMMY;
wiringPiSPIDataRW(0,data,1);
adcHigh=data[0];
//adcHigh &= 0b11000000;
//adcHigh <<=2;
//adc += adcHigh;
printf("ADC %d heeft waarde %x %x \n",kanaal, adcHigh, adc);
status=IDLE;
break;
case SELECTADC :
data[0]=SELECTADC;
wiringPiSPIDataRW(0,data,1);
data[0]=DUMMY;
wiringPiSPIDataRW(0,data,1);
if(data[0]==ACK){
delay(10);
data[0]=kanaal;
wiringPiSPIDataRW(0,data,1);
printf("ADC %s is succesfully selected",kanaal);
status=POLL;
}
else{
printf("There was an error selecting the ADC");
status=SELECTADC;
error+=1;
if(error==20){
status=POLL;
error=0;
printf("No ADC selected");
break;
}
}
break;
default :
printf("default\n");
break;
}
kanaal=0;
}
}
And Atmega32
#include <stdlib.h>
#include <avr/io.h>
void adc_init(void);
void SPI_SlaveInit(void);
unsigned char SPI_SlaveReceive(unsigned char);
void leesADC(char);
#define IDLE 1
#define POLL 2
#define ADCSTART 3
#define ADCSTATE 4
#define SELECTADC 6
#define READY 8
#define ACK 10
#define GIVEADC 32
#define NOTREADY 0x10
#define DUMMY 0x55
void SPI_SlaveInit(void)
{
/* Set MISO output, all others input */
DDRB = (1<<PB6);
/* Enable SPI */
SPCR = (1<<SPE);
}
unsigned char SPI_SlaveReceive(unsigned char data)
{
SPDR = data;
/* Wait for reception complete */
while(!(SPSR & (1<<SPIF) ));
/* Return data register */
return SPDR;
}
//starADC
void leesADC(char kanaal)
{
ADMUX &= 0b11100000;
ADMUX |= kanaal & 7;
ADCSRA |= (1<<ADSC);
}
void adc_init(void)
{
ADMUX=(1<<REFS0)|(1<<ADLAR); //voedings U als referentie, links uitlijnen in de 10bit
ADCSRA=(1<<ADEN); // adc enablen, start conversion, auto trigger enable
}
int main(void)
{
DDRC= 0b11111111;
DDRD= 0b11111111;
SPI_SlaveInit();
adc_init();
int kanaal=0;
leesADC(kanaal);
char stap;
char status;
while(1)
{
switch(stap){
case IDLE :
stap = SPI_SlaveReceive(status);
break;
case POLL :
status = ACK;
stap=IDLE;
PORTD=15;
break;
case ADCSTART :
status = ADCSTART;
leesADC(kanaal);
PORTD=255;
break;
case ADCSTATE :
if ((ADCSRA & (1<<ADIF)) == 0){
status = NOTREADY;
} else{
status = READY;
}
stap=IDLE;
break;
case GIVEADC :
stap= ADCH;
break;
case SELECTADC :
kanaal = SPI_SlaveReceive(DUMMY);
stap=DUMMY;
break;
default : ;
}
}
}
Thanks in advance.
You don't initialize the stap variable, which means its value will be indeterminate. Attempting to use it in the switch statement will lead to undefined behavior.
I suppose you should be initializing it to IDLE:
int stap = IDLE;

SPI on linux(raspberry PI) using spidev

I'm trying to use SPI on Raspberry PI using spidev and his test code as skeleton for my own. I have a problem with table size. My table has different size before I pass it to transfer function i.e. my table has 3 elements, inside function it has 4. Here is my code:
// spi.cpp : Defines the entry point for the console application.
//
#include <stdint.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/types.h>
#include <linux/spi/spidev.h>
#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
static const char *device = "/dev/spidev0.0";
static uint8_t mode;
static uint8_t bits = 8;
static uint32_t speed = 1000000;
static uint16_t delay;
//this function gives problems with diffrent size of array
static void transfer(int fd, uint8_t tx[])
{
printf("transfer1");
printf(" rozmiar tab=%d ", ARRAY_SIZE(tx));
int ret;
uint8_t rx[ARRAY_SIZE(tx)] = { 0, };
struct spi_ioc_transfer tr = {
.tx_buf = (unsigned long)tx,
.rx_buf = (unsigned long)rx,
.len = 3,
.delay_usecs = delay,
.speed_hz = speed,
.bits_per_word = bits,
};
ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
for (ret = 0; ret < ARRAY_SIZE(tx); ret++) {
if (!(ret % 6))
puts("");
printf("%d. %.2X ", ret,rx[ret]);
}
puts("");
}
int main(int argc, char *argv[])
{
int ret = 0;
int fd;
fd = open(device, O_RDWR);
/*
* spi mode
*/
ret = ioctl(fd, SPI_IOC_WR_MODE, &mode);
ret = ioctl(fd, SPI_IOC_RD_MODE, &mode);
/*
* bits per word
*/
ret = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits);
ret = ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &bits);
/*
* max speed hz
*/
ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed);
ret = ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed);
printf("spi mode: %d\n", mode);
printf("bits per word: %d\n", bits);
printf("max speed: %d Hz (%d KHz)\n", speed, speed / 1000);
uint8_t tx1[] = {
0x0, 0x1b, 0xa5
};
//here I'm passing table to function
transfer(fd, tx1);
uint8_t tx2[] = {
0x0, 0x33, 0x30, 0x01, 0x02
};
printf(" %d. ", ARRAY_SIZE(tx2));
transfer(fd, tx2);
uint8_t tx3[] = {
0x0, 0x52, 0x90
};
transfer(fd, tx3);
uint8_t tx4[] = {
0x80, 0x60
};
printf(" %d. ", ARRAY_SIZE(tx4));
transfer(fd, tx4);
close(fd);
return ret;
}
An array sent as a parameter to a function is treated as a pointer. Your ARRAY_SIZE(a) is roughly expanded to (sizeof(uint8_t*) / sizeof(uint8_t)), which equals 4 on 32-bit platform.
You should explicitly pass array size as a 3rd parameter:
void transfer(int fd, const uint8_t *tx, size_t size) { ... }
Then, you can use your macro to properly calculate array size:
transfer(fd, tx1, ARRAY_SIZE(tx1));
If tx is not being modified inside transfer(), it is a matter of good taste to make it const.

Resources