Peter Valencic Posted July 20, 2017 Posted July 20, 2017 Hi Martin and others I started a new Thread because have problems using some third party interfaces with OrangePI running Armbian. Well.. In my project I need to communicate with 5 sensors which have UART output so I decided to buy a circuit (uart2spi) which work well if connected to Arduino. The Circuit description is available here: http://www.rowlandtechnology.com/projects/2015/09/25/spi-to-4-x-uart-bridge-multiuart-project/ First step: This is how I have connected the circuit to GPIO bus on my OrangePi pc.. The circuit has (from left to right) +3.3V pin, MISO, MOSI, SCK (clock), CS and GND.. I have connected those wires to GPIO pins: +3.3V to pin 17 MOSI to pin 19 MISO to pin 21 SCK to pin 23 CS to pin 24 (chip select) GND to pin 20 This is how it look like... (the green led on my interface is on so it's mean that power is on) If I look at the tutorial on how to setup the board on Arduino is the same (you just connect wires) except CS is some output pin which you can togle on/off.. in my case I have connected those wire to orangepi on pin 24 (CE0).. Now I would like to port Arduino library to C and here the problems begin... first... the initialization of SPI... In Arduino I have this kind of method (SPIDivider is set to 250000 (250 kHz)) Arduino code: void MULTIUART::initialise(int SPIDivider) { SPI.begin(); SPI.setBitOrder(MSBFIRST); SPI.setClockDivider(SPIDivider); } and here is my code in C but I don't know if this is the right way to write over spi? and also how to set-up bitOrderMask (if needed)? Orangepi code : #include <iostream> #include <stdint.h> #include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <getopt.h> #include <fcntl.h> #include <sys/ioctl.h> #include <sys/times.h> #include <linux/types.h> #include <linux/spi/spidev.h> #include <spi_lib.h> using namespace std; #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) static const char *device = "/dev/spidev0.0"; static uint8_t mode = 3; static uint8_t bits = 8; static uint32_t speed = 250000; //250kHz static uint16_t delays; static void pabort(const char *s) { perror(s); abort(); } int main(int argc, char** argv) { int ret = 0; int fd; fd = open(device, O_RDWR); //read write if (fd < 0) { printf("can't open device"); return -1; } ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed); if (ret == -1) { printf("can't open device"); return -1; } printf("spi mode: %d\n", mode); printf("bits per word: %d\n", bits); printf("max speed: %d Hz (%d KHz)\n", speed, speed / 1000); if (ioctl(fd, SPI_IOC_WR_MODE, &mode) == -1) pabort("Can't set SPI mode"); close(fd); return ret; } from console i get: now... Here I have a function from Arduino to set BaudRate for specified channel on my interface. (baud rate is selected with values from 0 to 7 (0=1200, 1=2400, 2=4800, 3=9600, 4=19200, 5=38400, 6=57600, 7=115200)) This function works well on Arduino (but.... if you see it uses digitalWrite command to pull down the signal on CS pin and then the command is send over SPI.transfer function.. ) void MULTIUART::SetBaud(char UART, char BAUD) { if (UART < 4) { if (BAUD < 10) { digitalWrite(_ss_pin, LOW); SPI.transfer(0x80 | UART); delayMicroseconds(50); SPI.transfer(BAUD); digitalWrite(_ss_pin, HIGH); delayMicroseconds(50); } } } Now I don't know if the same must be done on OrangePI with CS pin (pin 24 on GPIO or is this done by kernel)? I have ported this code above on orangepi like this: void setBaudRate(int fd,char uart) { if (uart <4) { int ret = -1; uint8_t tx_buffer_baud = (uint8_t)(0x80|uart); //??? CS pin must be in LOW mode ret = spi_write(fd,&tx_buffer_baud,1); printf("ret1: %d\n", ret); usleep(50); tx_buffer_baud = (uint8_t) 3; ret = spi_write(fd,&tx_buffer_baud,1); usleep(50); //??? CS pin must be in HIGH mode printf("ret1: %d\n", ret); } } So is the CS pin set to LOW before the command is send over SPI or it must be done manually? thank you for any info..
adrb Posted July 20, 2017 Posted July 20, 2017 22 minutes ago, Peter Valencic said: So is the CS pin set to LOW before the command is send over SPI or it must be done manually? CS is handled by kernel, you shouldn't set it manually.
Peter Valencic Posted July 20, 2017 Author Posted July 20, 2017 ok.. I tryed with this code below... #include <iostream> #include <stdint.h> #include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <getopt.h> #include <fcntl.h> #include <sys/ioctl.h> #include <sys/times.h> #include <linux/types.h> #include <linux/spi/spidev.h> #include <spi_lib.h> using namespace std; #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) static const char *device = "/dev/spidev0.0"; static uint8_t mode = 3; static uint8_t bits = 8; static uint32_t speed = 250000; //250kHz static uint16_t delays; static void pabort(const char *s) { perror(s); abort(); } void setBaudRate(int fd, char uart) { if (uart < 4) { int ret = -1; uint8_t tx_buffer_baud = (uint8_t) (0x80 | uart); //9600 baud rate UART 1 ret = spi_write(fd, &tx_buffer_baud, 1); printf("ret1: %d\n", ret); usleep(150); tx_buffer_baud = (uint8_t) 3; ret = spi_write(fd, &tx_buffer_baud, 1); usleep(150); printf("ret1: %d\n", ret); } } void TransmitString(int fd, char uart, char *DATA, char NUMBYTES) { char IDX = (0x0); int ret = -1; if (uart < 4) { uint8_t tx_buffer_baud = (uint8_t) (0x40 | uart); //9600 baud rate UART 1 ret = spi_write(fd, &tx_buffer_baud, 1); usleep(150); tx_buffer_baud = (uint8_t) (NUMBYTES); ret = spi_write(fd, &tx_buffer_baud, 1); usleep(150); while (IDX < NUMBYTES) { tx_buffer_baud = (uint8_t) DATA[IDX]; ret = spi_write(fd, &tx_buffer_baud, 1); usleep(150); IDX = IDX + 1; } usleep(150); } } int main(int argc, char** argv) { int ret = 0; int fd; fd = open(device, O_RDWR); //read write if (fd < 0) { printf("can't open device"); return -1; } /* * 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) printf("can't set bits per word"); ret = ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &bits); if (ret == -1) printf("can't get bits per word"); /* * max speed hz */ ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed); if (ret == -1) printf("can't set max speed hz"); ret = ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed); if (ret == -1) printf("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); //set baud rate // Initialise the UART baud rates // 0=1200, 1=2400, 2=4800, 3=9600, 4=19200, 5=38400, 6=57600, 7=115200 setBaudRate(fd, 0); //UART 1 TransmitString(fd,0,"PETER",5); close(fd); return ret; } and connected the interface with USB/AURT cable... On My PC RS232terminal I now receive some "garbage"...
Peter Valencic Posted July 21, 2017 Author Posted July 21, 2017 Friday magic friday Solved... Have changed SPI mode to 0 and now it works well
adrb Posted July 21, 2017 Posted July 21, 2017 Glad to hear that and thanks for sharing. Often people tend to forget share their final solution
Recommended Posts