SPI COMM in Atmega328p - c

I am working on Atmega328p using Arduino Uno board, my task is SPI comm using register level,
can anybody explain what is meant by DD_MOSI is left shift "1<

I assume you are referring to the code examples on page 172 of the ATmega328p datasheet (http://ww1.microchip.com/downloads/en/DeviceDoc/ATmega48A-PA-88A-PA-168A-PA-328-P-DS-DS40002061A.pdf). In the example, they use DD_MOSI as a stand in for the bit position of the control bit for the pin associated with MOSI signal, which on the MCU in question is PortB[3]. So, when they have the line:
DDR_SPI = (1<<DD_MOSI)|(1<<DD_SCK);
You can translate that to fill in the associated port and bit shifts:
DDRB = (1<<DDB3)|(1<<DDB5); // Since SPI in on Port B, MOSI is the third pin and SCK is the 5th pin, see page 91-92

Related

Proper use of SPI functions in RP2040 C/C++ SDK with PGA2310 volume control IC

I've been working on a project where I use a PGA2310 volume control IC to set the volume of an audio signal. The chip's interface is supposedly SPI, but no matter how much I try, I just can't seem to get it right. The chip takes a 16 bit word over SPI that contains the left and right channel volume information.
I'm wondering if I am using the sdk all wrong and my code is whacked.
I guess my question is: Am I setting up and using the SPI functions correctly?
Here is my code
/**
* SPI interface for PGA2310 volume control ic
*/
#include "pico/stdlib.h"
#include "hardware/spi.h"
#include "pico/time.h"
const int CS = 0;
const int SDI = 1;
const int SCLK = 2;
const int LED_PIN16 = 16;
const int LED_PIN25 = 25;
uint16_t PGA2310();
uint16_t PGA2310() {
int baud = 1600000;
// SPI inistalization
spi_init(spi0, baud);
spi_set_format(spi0, 16, SPI_CPOL_0 , SPI_CPHA_0, SPI_MSB_FIRST);
// Sets SPI pins
gpio_set_function(CS, GPIO_FUNC_SPI);
gpio_set_function(SDI, GPIO_FUNC_SPI);
gpio_set_function(SCLK, GPIO_FUNC_SPI);
// Sets LED pins
gpio_init(LED_PIN16);
gpio_set_dir(LED_PIN16, GPIO_OUT);
gpio_init(LED_PIN25);
gpio_set_dir(LED_PIN25, GPIO_OUT);
// Data to send to chip. only sending first 8 bits for right channel.
// This is because I am currently just testing the output of the right channel
uint16_t high = 255;
uint16_t low = 100;
// Test by toggling between high and low volume states with LED indicators
while (true) {
gpio_put(LED_PIN25, 1);
spi_write16_blocking(spi0, &high, 1);
sleep_ms(2000);
gpio_put(LED_PIN25, 0);
spi_write16_blocking(spi0, &low, 1);
sleep_ms(2000);
}
}
I've tried a bunch of different methods that I found online for using SPI with the pico SDK. I've tried just sending 8 bits.
Let me know if more info is needed.
As explained in comments, SPI normally consists of 4 signals: /SS, SCLK, MOSI and MISO.
/SS = slave select, also known as chip select. Almost always active low.
SCLK = serial clock.
MOSI = Master Output Slave Input. The main data line. Your MCU seems to call this SDO (serial data out?).
MISO = Master Input Slave Output. Optional signal for duplex (two way) communication SPI. Your MCU seems to call this SDI (serial data input).
In this case the MCU is the master so you should be using MOSI/SDO. A MCU is almost always the master, except when communicating with other MCUs.
Additionally, always double check which CPOL and CPHA settings that the slave expects. Getting these wrong is a classic problem and can lead to subtle "clock skew" problems where everything works fine most of the time, then fail and give corrupt data intermittently.
The names you pick for variables/constants in C code do not have any effect on the hardware and they disappear as soon as the code is compiled. The most important thing is that you understand how the hardware works, read the documentation for the RP2040 SDK functions you are calling, and then pass the correct values to the RP2040 SDK functions.
The biggest problem is that you need to rethink every pin assignment. The RP2040 hardware SPI pin functions are defined in column F1 of the "GPIO Functions" section of the RP2040 datasheet. Here is an excerpt from that table:
This table tells us, for example, you cannot use pin 0 as the SPI0 CS function. If you assign that pin to be an SPI pin, it will be the SPI0 RX (data receiving) pin.
At a minimum, you need to pick one pin to be the SPI0 SCK pin and another to be the SPI0 TX pin, and you must connect those pins from the RP2040 to the equivalent pins on your device. Then you might also need to pick an RP2040 pin to control the CS pin on your device, if it has one. On the RP2040 side, this pin would be configured as a GPIO output pin and you would drive it low or high to enable your device. Refer to your device's datasheet for details about what signals it expects on its inputs and then use an oscilloscope to make sure you are generating compliant signals.
Another problem is that the spi_write16_blocking is probably modifying your high and low variables, so you will probably need to set those to the right values before each time that you use them. (So there is no point in having two different variables like that, just have one.)

Programming the MCP4141 digital potentiometer in STM32CUBEIDE by SPI port

I am trying to program a Microchip MCP4141 digital potentiometer with the STM32CUBEIDE development environment using a NUCLEO F334R8 board. I am sending a 16 bit command through the SPI communications port. When I send the command byte with the data byte, I cannot notice voltage variations between the P0A and P0W terminals of the MCP4141.
Could you help me find the programming error? Thanks
uint8_t data[2];
data[0]=0x00;
data[1]=0x0F;
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4,GPIO_PIN_RESET);
HAL_SPI_Transmit(&hspi1, data, 2, 500);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4,GPIO_PIN_SET);
Usually when an SPI peripheral does not work, the commands are not received by the slave chip. This can have multiple reasons:
Incorrect wiring (MOSI, MISO, CLK lines)
Incorrect SPI mode (clock phase, clock polarity) --> check SPI settings in CubeMX
Slave chip is in Reset because of incorrect/floating EN or RST Pin
Can you probe the data and clock lines? Do you see a signal being transmitted?
Alternatively, can you successfully read anything from the chips internal memory e.g. the status register?

Issue in interfacing E-Ink display with STM8S103F3P6 microcontroller

I am using Waveshare 1.54" ePaper Module. Using SPI peripheral:
CPU freq is 16Mhz
SPI Prescaler DIV by 8
MSB FIRST
CPOL=0, CPHA=1
The Display does not response but it respond with TI CC1310 properly.
The problem with SPI is after transmitting byte it does not go to ideal high state.
I have checked with logic analyser.
The SPI is initialised thus:
/****************** Initializing The SPI Peripheral ******************/
void SPI_setup(void)
{
CLK_PeripheralClockConfig(CLK_PERIPHERAL_SPI, ENABLE); //Enable SPI Peripheral Clock
//Set the MOSI, MISO and SCk at high Level.
//GPIO_ExternalPullUpConfig(GPIOC, (GPIO_Pin_TypeDef)(GPIO_PIN_6),ENABLE);
SPI_DeInit();
SPI_Init(SPI_FIRSTBIT_MSB, //Send MSB First
SPI_BAUDRATEPRESCALER_8, //Fosc/16 = 1MHz
SPI_MODE_MASTER,
SPI_CLOCKPOLARITY_LOW, //IDEAL Clock Polarity is LOW
SPI_CLOCKPHASE_2EDGE, //The first clock transition is the first data capture edge
SPI_DATADIRECTION_2LINES_FULLDUPLEX, //Only TX is Enable
SPI_NSS_SOFT,
0x00);
SPI_Cmd(ENABLE);
}
This is pretty much the same problem you had at Issue in interfacing SPI e-ink display with PIC 18F46K22 only on a different processor. Worth noting that CPHA on STM8 has the opposite sense to CPE on PIC18 which may be the cause of your error. That is to say that CPHA=1 on the STM8 has the same effect as CKE=0 on the PIC18. You really have to look at the timing diagrams for each part carefully.
From https://www.waveshare.com/wiki/1.54inch_e-Paper_Module:
Compare with the STM8 reference manual:
Clearly you need one of:
CPHA=1 / CPOL=1 (SPI_CLOCKPOLARITY_HIGH / SPI_CLOCKPHASE_2EDGE) or
CPHA=0 / CPOL=0 (SPI_CLOCKPOLARITY_LOW / SPI_CLOCKPHASE_1EDGE)
If it is the SCLK that you want to be normally-high, then you need the first option - although I fail to see why that is "ideal", the Waveshare diagram clearly indicates that either is acceptable.

Sparkfun SC16IS750 does not work on Raspberry Pi

I'm connecting a SC16IS750 spi-2-uart bridge to the Raspberry Pi 2 in order to increase the number of uart ports. The product is a breakout board made by Sparkfun (https://www.sparkfun.com/products/9981), utilizing the SC16IS750 chip (http://www.nxp.com/documents/data_sheet/SC16IS740_750_760.pdf). I use the BCM2835 library by Mike McCauley to access SPI.
The problem is, whichever register I try to read, I invariably get back 0xff. For example,
uint8_t tx[2];
tx[0] = 0x07 << 3 | 0x80; // SPR register
tx[1] = 0x00;
uint8_t rx[2] = {0x00, 0x00};
// perform duplex write operation
bcm2835_spi_transfernb(tx, rx, 2);
rx[0] and rx[1] returns 0xff. It doesn't matter which register I try to read, the result is the same.
The breakout board already grounds the reset pin. I connect the CS pin to SSEL1, CLK to GPIO11, SI to GPIO10, SO to GPIO9, and SPI/I2C to ground. I tried with another chip, same response. SPI works fine since I also use it successfully with another peripheral.
Any idea on what I should try next?
Turns out the problem is the clock divider. Setting the SPI clock divider to 256 and above
bcm2835_spi_setClockDivider(BCM2835_SPI_CLOCK_DIVIDER_256)
resolved the problem.

example code, documents on MCP23017 (16 pin IO extender, I2C) as an 7-segment LCD driver

the MCP23017 from Microchip is an I2C based 16-pin IO extender. I have been able to set up the device once (set pin direction and values), but after that i cannot change the values as expected unless i reset / power cycle the device. this is the code i used to initalize it and set the pins up the first time:
I2C_Start();
I2C_Write(0x40); // slave address
I2C_Write(0x00); // address register
... (sequential mode so next 10 are set to I2C_Write(0x00);
I2C_Write(0x08); // IOCON: HAEN=1
I2C_Write(0x08); // IOCON: HAEN=1
... (sequential mode so next 6 are set to I2C_Write(0x00);
I2C_Write(0xFEu); // GPIOA
I2C_Write(0x01u); // GPIOB
I2C_Stop();
after this i would like to be able to toggle the output values (0xFE <-> 0x01).
I attempted this code:
I2C_Start();
I2C_Write(0x40); // slave address
I2C_Write(0x12); // address register
I2C_Write(0x01u); // GPIOA
I2C_Write(0xFEu); // GPIOB
I2C_Stop();
at this point it seems to go out to lunch, the pins seem to be random in value (input vs. output, output High vs Low). If anyone as used this I2C IO extender please help me out. even if your not fully sure your more than welcome to comment. NOTE: I2C API shown here is a bit bang algorithm all clock cycles have aprox. 1ms weights between them.
useful documents (kind of): http://ww1.microchip.com/downloads/en/DeviceDoc/21952b.pdf
Try looking at the SCL and SDA signals using an oscilloscope or logic analyzer to check your timing and the data to make sure you are sending the I/O expander the values you think you are.

Resources