I am programming a microcontroller using Kinetis Design Studio(KDS) and i want to implement an interrupt such that at anytime during runtime if a specific I/O pin has a "high" level the microcontroller should stop working until the pin is back to "low" .
Any ideas?
Try this code from free scale forum
https://www.element14.com/community/community/designcenter/kinetis_kl2_freedom_board/blog/2015/08/21/kinetis-design-studio-30-kinetis-sdk-12-processor-expert-using-frdm-kl43z-quick-tutorial-on-gpio-interrupt-toggling-led-using-button-with-interrupt-logic
or
below is an usart interrupt code you can modify it
/* p6_4.c UART0 Receive using interrupt */
/* This program modifies p4_2.c to use interrupt to handle the UART0 receive.
Receiving any key from terminal emulator (TeraTerm) of the host PC to the UART0 on Freescale FRDM-KL25Z board.
UART0 is connected to openSDA debug agent and has a virtual connection to the host PC COM port.
Launch TeraTerm on a PC and hit any key.
The LED program from P2_7 of Chapter 2 is used to turn on the tri-color LEDs according to the key received.
By default in SystemInit(), FLL clock output is 41.94 MHz.
Setting BDH=0, BDL=0x17, and OSR=0x0F yields 115200 Baud. */
#include <MKL25Z4.H>
void UART0_init(void);
void delayMs(int n);
void LED_init(void);
void LED_set(char value);
int i=0;
int main (void) {
__disable_irq(); /* global disable IRQs */
UART0_init();
LED_init();
__enable_irq(); /* global enable IRQs */
while (1) {
/* UART0 receive is moved to interrupt handler*/
}
}
/* UART0 interrupt handler */
void UART0_IRQHandler(void)
{
char c;
c = UART0->D; /* read the char received */
LED_set(c); /* and use it to set LEDs */
}
/* initialize UART0 to receive at 115200 Baud */
void UART0_init(void)
{
SIM->SCGC4 |= 0x0400; /* enable clock for UART0 */
SIM->SOPT2 |= 0x04000000; /* use FLL output for UART Baud rate generator */
UART0->C2 = 0; /* turn off UART0 while changing configurations */
UART0->BDH = 0x00;
UART0->BDL = 0x17; /* 115200 Baud */
UART0->C4 = 0x0F; /* Over Sampling Ratio 16 */
UART0->C1 = 0x00; /* 8-bit data */
UART0->C2 = 0x24; /* enable receive and receive interrupt*/
NVIC->ISER[0] |= 0x00001000; /* enable INT12 (bit 12 of ISER[0]) */
SIM->SCGC5 |= 0x0200; /* enable clock for PORTA */
PORTA->PCR[1] = 0x0200; /* make PTA1 UART0_Rx pin */
}
/* initialize all three LEDs on the FRDM board */
void LED_init(void)
{
SIM->SCGC5 |= 0x400; /* enable clock to Port B */
SIM->SCGC5 |= 0x1000; /* enable clock to Port D */
PORTB->PCR[18] = 0x100; /* make PTB18 pin as GPIO */
PTB->PDDR |= 0x40000; /* make PTB18 as output pin */
PTB->PSOR |= 0x40000; /* turn off red LED */
PORTB->PCR[19] = 0x100; /* make PTB19 pin as GPIO */
PTB->PDDR |= 0x80000; /* make PTB19 as output pin */
PTB->PSOR |= 0x80000; /* turn off green LED */
PORTD->PCR[1] = 0x100; /* make PTD1 pin as GPIO */
PTD->PDDR |= 0x02; /* make PTD1 as output pin */
PTD->PSOR |= 0x02; /* turn off blue LED */
}
/* turn on or off the LEDs according to bit 2-0 of the value */
void LED_set(char value)
{
if (value=='c')
{ /* use bit 1 of value to control green LED */
PTB->PCOR = 0x80000; /* turn on green LED */
s }
if (~(value=='c') )
{ /* use bit 1 of value to control green LED */
PTB->PSOR = 0x80000; /* turn off green LED */
}
}
Related
I am currently working to configurate SPI communication in a SAMD51 board. After a lot of research I could find how to setup the registers to start the pin configuration and clock setup, among other things. But there is one procedure in the end of the setup that requires to enable the pin again.
Here is the datasheet for the MCU https://www.mouser.com/datasheet/2/268/60001507A-1130176.pdf
SERCOM4->SPI.CTRLA.bit.ENABLE = 1;
After I call this line the library freezes and I cannot get any other response.
find bellow the cpp file.
#include "SercomSPISlave.h"
// Constructors //
SercomSPISlave::SercomSPISlave()
{
}
// Public Methods //
void SercomSPISlave::Sercom4init()
{
//Setting up NVIC
NVIC_EnableIRQ(SERCOM4_0_IRQn);
NVIC_SetPriority(SERCOM4_0_IRQn,2);
//MCLK->APBDMASK.reg |= MCLK_APBDMASK_SERCOM4;
MCLK->APBDMASK.bit.SERCOM4_ = 1;
//Setting Generic Clock Controller!!!!
//GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID(GCM_SERCOM4_CORE) | //Generic Clock 0
// GCLK_CLKCTRL_GEN_GCLK0 | // Generic Clock Generator 0 is the source
// GCLK_CLKCTRL_CLKEN; // Enable Generic Clock Generator
GCLK->PCHCTRL[34].reg = GCLK_PCHCTRL_GEN_GCLK0 | GCLK_PCHCTRL_CHEN;
//while(GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY); //Wait for synchronisation
//Configure SERCOM4 SPI PINS
//Set PA12 as input (MOSI) - on D22 / MISO
//Set PB09 as input (SCK) - on A2
//Set PB10 as input (SS) - on D23 / MOSI
//Set PB11 as output (MISO) - on D24 / SCK
PORT->Group[PORTB].PINCFG[11].bit.PMUXEN = 0x1; //Enable Peripheral Multiplexing for SERCOM4 SPI PB11
PORT->Group[PORTB].PMUX[11 >> 1].bit.PMUXO = 0x3; //SERCOM 4 is selected for peripheral use of this pad (0x3 selects peripheral function D: SERCOM-ALT)
PORT->Group[PORTB].PINCFG[12].bit.PMUXEN = 0x1; //Enable Peripheral Multiplexing for SERCOM4 SPI PB12
PORT->Group[PORTB].PMUX[12 >> 1].bit.PMUXE = 0x3; //SERCOM 4 is selected for peripheral use of this pad (0x3 selects peripheral function D: SERCOM-ALT)
PORT->Group[PORTB].PINCFG[13].bit.PMUXEN = 0x1; //Enable Peripheral Multiplexing for SERCOM4 SPI PB13
PORT->Group[PORTB].PMUX[13 >> 1].bit.PMUXO = 0x3; //SERCOM 4 is selected for peripheral use of this pad (0x3 selects peripheral function D: SERCOM-ALT)
PORT->Group[PORTA].PINCFG[9].bit.PMUXEN = 0x1; //Enable Peripheral Multiplexing for SERCOM4 SPI PB09
PORT->Group[PORTA].PMUX[9 >> 1].bit.PMUXO = 0x3; //SERCOM 4 is selected for peripheral use of this pad (0x3 selects peripheral function D: SERCOM-ALT)
/*
Explanation:
PMUXEN stands for Peripheral Multiplexing Enable
PMUXE stands for Even bits in the Peripheral Multiplexing register
PMUXO stands for Odd bits in the Peripheral Multiplexing register
The selection of peripheral function A to H is done by writing to the Peripheral Multiplexing Odd and Even bits in the Peripheral Multiplexing register (PMUXn.PMUXE/O) in the PORT.
Reference: Atmel-42181G-SAM-D21_Datasheet section 6.1 on page 21
PA12 corresponds to: PORTA, PMUX[6] Even
PB09 corresponds to: PORTB, PMUX[4] Odd
PB10 corresponds to: PORTB, PMUX[5] Even
PB11 corresponds to: PORTB, PMUX[5] Odd
In general:
Px(2n+0/1) corresponds to Portx, PMUX[n] Even=0/Odd=1*/
//Disable SPI 1
SERCOM4->SPI.CTRLA.bit.ENABLE =0;
while(SERCOM4->SPI.SYNCBUSY.bit.ENABLE);
//Reset SPI 1
SERCOM4->SPI.CTRLA.bit.SWRST = 1;
while(SERCOM4->SPI.CTRLA.bit.SWRST || SERCOM4->SPI.SYNCBUSY.bit.SWRST);
//Set up SPI Control A Register
SERCOM4->SPI.CTRLA.bit.DORD = 0; //MSB first
SERCOM4->SPI.CTRLA.bit.CPOL = 0; //SCK is low when idle, leading edge is rising edge
SERCOM4->SPI.CTRLA.bit.CPHA = 0; //data sampled on leading sck edge and changed on a trailing sck edge
SERCOM4->SPI.CTRLA.bit.FORM = 0x0; //Frame format = SPI
SERCOM4->SPI.CTRLA.bit.DIPO = 0x0; //DATA PAD0 MOSI is used as slave input (slave mode) // page 492
SERCOM4->SPI.CTRLA.bit.DOPO = 0x2; //DATA PAD2 MISO is used as slave output
SERCOM4->SPI.CTRLA.bit.MODE = 0x2; //SPI in Slave mode
SERCOM4->SPI.CTRLA.bit.IBON = 0x1; //Buffer Overflow notification
SERCOM4->SPI.CTRLA.bit.RUNSTDBY = 1; //wake on receiver complete
//Set up SPI control B register
//SERCOM4->SPI.CTRLB.bit.RXEN = 0x1; //Enable Receiver
SERCOM4->SPI.CTRLB.bit.SSDE = 0x1; //Slave Selecte Detection Enabled
SERCOM4->SPI.CTRLB.bit.CHSIZE = 0; //character size 8 Bit
//SERCOM4->SPI.CTRLB.bit.PLOADEN = 0x1; //Enable Preload Data Register
//while (SERCOM4->SPI.SYNCBUSY.bit.CTRLB);
//Set up SPI interrupts
SERCOM4->SPI.INTENSET.bit.SSL = 0x1; //Enable Slave Select low interrupt
SERCOM4->SPI.INTENSET.bit.RXC = 0x1; //Receive complete interrupt
SERCOM4->SPI.INTENSET.bit.TXC = 0x1; //Receive complete interrupt
SERCOM4->SPI.INTENSET.bit.ERROR = 0x1; //Receive complete interrupt
SERCOM4->SPI.INTENSET.bit.DRE = 0x1; //Data Register Empty interrupt
//init SPI CLK
//SERCOM4->SPI.BAUD.reg = SERCOM_FREQ_REF / (2*4000000u)-1;
//Enable SPI
SERCOM4->SPI.CTRLB.bit.RXEN = 0x1; //Enable Receiver, this is done here due to errate issue
while(SERCOM4->SPI.SYNCBUSY.bit.CTRLB); //wait until receiver is enabled
Serial.begin(115200);
SERCOM4->SPI.CTRLA.bit.ENABLE = 1;
Serial.print(SERCOM4->SPI.CTRLA.bit.ENABLE);
while(SERCOM4->SPI.SYNCBUSY.bit.ENABLE);
}
Find bellow the .h file.
#ifndef SercomSPISlave_h
#define SercomSPISlave_h
#include <Arduino.h>
class SercomSPISlave
{
public:
// Constructors //
SercomSPISlave();
// Public Methods //
void Sercom4init();
};
#endif
Find bellow the .ino code
#include <SercomSPISlave.h>
SercomSPISlave SPISlave;
void setup()
{
Serial.begin(115200);
Serial.println("Serial started");
SPISlave.Sercom4init();
while(!Serial);
Serial.println("Sercom1 SPI slave initialized!");
}
void loop()
{
}
I appreciate any support you can give me.
I've created a PCB with a STM32F207ZET6 and it has an NXP NFC chip connected via I2C.
The problem that I am having is that I can not communicate with the NFC chip.
I have verified the I2C connection between the ARM chip and NFC.
I have verified that both chips are getting the correct power.
I am using stm32cube IDE with a stlink-v3.
I configured the I2C1 pins and wrote the following code.
What I have tried
I have tried to use HAL_I2C_IsDeviceReady() to see if the NFC was connected. This returns true, but it also returns true on every address that I put in there.
I have tried to send commands and also read them back into a buffer array. All that was returned was 0.
cmds[1] = 0x60;
cmds[2] = 0x00;
HAL_I2C_Master_Transmit(&hi2c1, nfc_Adr_w, cmds, 2, HAL_MAX_DELAY);
HAL_Delay(15);
HAL_I2C_Master_Transmit(&hi2c1, nfc_Adr_w, cmds, 1, HAL_MAX_DELAY);
HAL_I2C_Master_Receive(&hi2c1, nfc_Adr_r, buffer, 1, HAL_MAX_DELAY);
Any help would be greatly appreciated, thank you.
Full Code
#include "main.h"
/* Private variables ---------------------------------------------------------*/
I2C_HandleTypeDef hi2c1;
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_I2C1_Init(void);
unsigned char buffer[150];
unsigned char cmds[3];
_Bool results = 0;
uint8_t devices = 0u;
int deviceReady = 0u;
/* Private user code ---------------------------------------------------------*/
/**
* #brief The application entry point.
* #retval int
*/
int main(void)
{
uint8_t nfc_Adr_w = 0b10101010;
uint8_t nfc_Adr_r = 0b10101011;
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_I2C1_Init();
/* USER CODE BEGIN 2 */
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
//HAL_I2C_Master_Transmit();
//HAL_I2C_Master_Receive();
cmds[0] = 0x00;
cmds[1] = 0x60;
cmds[2] = 0x00;
HAL_I2C_Master_Transmit(&hi2c1, nfc_Adr_w, cmds, 2, HAL_MAX_DELAY);
HAL_Delay(15);
HAL_I2C_Master_Transmit(&hi2c1, nfc_Adr_w, cmds, 1, HAL_MAX_DELAY);
HAL_I2C_Master_Receive(&hi2c1, nfc_Adr_r, buffer, 1, HAL_MAX_DELAY);
// deviceReady = HAL_I2C_IsDeviceReady(&hi2c1, 0x3C, 3u, 10u);
// printf("Searching for I2C devices on the bus...\n");
/* Values outside 0x03 and 0x77 are invalid. */
// for (uint8_t i = 0x03u; i < 0x78u; i++)
// {
// uint8_t address = i << 1u;
// /* In case there is a positive feedback, print it out. */
// if (HAL_OK == HAL_I2C_IsDeviceReady(&hi2c1, address, 3u, 10u))
// {
//// printf("Device found: 0x%02X\n", address);
// devices++;
// results = 1;
// }
// if (HAL_TIMEOUT == HAL_I2C_IsDeviceReady(&hi2c1, address, 3u, 10u)) {
// devices++;
// }
// deviceReady = HAL_I2C_IsDeviceReady(&hi2c1, address, 3u, 10u);
// }
// /* Feedback of the total number of devices. */
//// if (0u == devices)
//// {
////// printf("No device found.\n");
//// }
//// else
//// {
//// printf("Total found devices: %d\n", devices);
//// }
HAL_Delay(1000u);
devices = 0u;
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
/**
* #brief System Clock Configuration
* #retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
/** Initializes the CPU, AHB and APB busses clocks
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB busses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
{
Error_Handler();
}
}
/**
* #brief I2C1 Initialization Function
* #param None
* #retval None
*/
static void MX_I2C1_Init(void)
{
/* USER CODE BEGIN I2C1_Init 0 */
/* USER CODE END I2C1_Init 0 */
/* USER CODE BEGIN I2C1_Init 1 */
/* USER CODE END I2C1_Init 1 */
hi2c1.Instance = I2C1;
hi2c1.Init.ClockSpeed = 100000;
hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2;
hi2c1.Init.OwnAddress1 = 0;
hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
hi2c1.Init.OwnAddress2 = 0;
hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
if (HAL_I2C_Init(&hi2c1) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN I2C1_Init 2 */
/* USER CODE END I2C1_Init 2 */
}
/**
* #brief GPIO Initialization Function
* #param None
* #retval None
*/
static void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_RESET);
/*Configure GPIO pin : LED_Pin */
GPIO_InitStruct.Pin = LED_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(LED_GPIO_Port, &GPIO_InitStruct);
}
/* USER CODE BEGIN 4 */
/* USER CODE END 4 */
/**
* #brief This function is executed in case of error occurrence.
* #retval None
*/
void Error_Handler(void)
{
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state */
/* USER CODE END Error_Handler_Debug */
}
#ifdef USE_FULL_ASSERT
/**
* #brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* #param file: pointer to the source file name
* #param line: assert_param error line source number
* #retval None
*/
void assert_failed(uint8_t *file, uint32_t line)
{
/* USER CODE BEGIN 6 */
/* User can add his own implementation to report the file name and line number,
tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
I am using MSO430F2418 for my project. I am sending Hello world message to Bluetooth module via UART pins. Also I need to set pin P2.3 to high to reset the Bluetooth. Unfortunately Im unable to set that perticuler pin to high. When I check the voltage at Reset pin of Bluetooth it is low.
You can see below two lines in my code. I have used these statements to set the P2.3.
P2DIR|=0x08;
P2OUT|=0x08;
I have attached an image. There you can see the hardware. enter image description here
#include <stdio.h>
#include <msp430.h>
const char string[] = { "Hello World\r\n" };
unsigned int i;
int main(void){
WDTCTL = WDTPW + WDTHOLD; // Stop WDT
if (CALBC1_1MHZ==0xFF) // If calibration constant erased
{
while(1); // do not load, trap CPU!!
}
DCOCTL = 0; // Select lowest DCOx and MODx settings
BCSCTL1 = CALBC1_1MHZ; // Set DCO
DCOCTL = CALDCO_1MHZ;
P2DIR|=0x08;
P2OUT|=0x08;
P3SEL = 0x30; // P3.4,5 = USCI_A0 TXD/RXD
UCA0CTL1 |= UCSSEL_3; // SMCLK
UCA0BR0 = 8; // 1MHz 115200
UCA0BR1 = 0; // 1MHz 115200
UCA0MCTL = UCBRS2 + UCBRS1; // Modulation UCBRSx = 5
UCA0CTL1 &= ~UCSWRST; // **Initialize USCI state machine**
// IE2 |= UCA0RXIE; // Enable USCI_A0 RX interrupt
IE2 |= UCA0TXIE;
__bis_SR_register(LPM0_bits + GIE); // Enter LPM0, interrupts enabled
}
#pragma vector=USCIAB0TX_VECTOR
__interrupt void USCI0TX_ISR(void)
{
UCA0TXBUF = string[i++]; // TX next character
if (i == sizeof string - 1){ // TX over?
IE2 &= ~UCA0TXIE; // Disable USCI_A0 TX interrupt
_delay_cycles(1000000);
i = 0;
IE2 |= UCA0TXIE; // Enable USCI_A0 TX interrupt
}
}
I've asked the same question on the ST Q&A forum and on the Raspberry Pi forum, but I didn't receive any answer. I hope that here there is someone that can help me.
I want to make communicate two Nucleo l432kc (slaves) with a Raspberry Pi (master) through the SPI protocol. On the Raspberry I'm using the Spidev API, while on the Nucleo I'm using the HAL SPI interface with DMA.
The only configuration that permits a stable transmission is the SPI_MODE_2 of Spidev that corresponds to the SPI_POLARITY_HIGH and SPI_PHASE_2EDGE configuration of the HAL.
With the above configuration I have two problems:
The messages sent by the master to the slaves arrive always correctly, but all the messages sent by the slaves to the master always arrive shifted by 1 bit on the right (e.g. if I send two bytes 0b00000011 0b00000001 I receive 0b00000001 0b10000000). It seems that the sampling of the MISO signal is delayed but I can't figure out why.
I receive the data on both the slaves regardless if the chip select is set or not. In the response of the slaves I have no collisions so I think that only the MISO bus is effectively set in high impedance mode in the slave when the NSS is high.
To test purpose I've tried to use the SPISlave class of the mbed framework,
this class cannot use the DMA so I can't use it in the real program. Using it I solve the first problem but the second persists.
Another thing that could be useful is that with the SPISlave class I can use all the 4 mode of the SPI protocol, of course the slaves and the master must use the same mode but is not import which one.
As I said before with the HAL interface I can use only the SPI_MODE_2.
This is the configuration code that runs on both the slaves:
// SPI
__HAL_RCC_SPI1_CLK_ENABLE();
/* SPI1 parameter configuration*/
hspi.Instance = SPI1;
hspi.Init.Mode = SPI_MODE_SLAVE;
hspi.Init.Direction = SPI_DIRECTION_2LINES; // full duplex mode
hspi.Init.DataSize = SPI_DATASIZE_8BIT; // dimension of 1 byte
hspi.Init.CLKPolarity = SPI_POLARITY_HIGH; // start and idle clk value
hspi.Init.CLKPhase = SPI_PHASE_2EDGE; // edge of sampling of data both on miso and mosi
hspi.Init.FirstBit = SPI_FIRSTBIT_MSB; // bit order
hspi.Init.TIMode = SPI_TIMODE_DISABLE; // disabling the TI mode
hspi.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE; // disable crc calc
hspi.Init.NSSPMode = SPI_NSS_PULSE_DISABLE; // disable NSS puls value
if (HAL_SPI_Init(&hspi) != HAL_OK)
return false;
/* SPI1 interrupt Init */
HAL_NVIC_SetPriority(SPI1_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(SPI1_IRQn);
// GPIO
GPIO_InitTypeDef GPIO_InitStruct = {0};
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
/**SPI1 GPIO Configuration
PA1 ------> SPI1_SCK
PA11 ------> SPI1_MISO
PA12 ------> SPI1_MOSI
PB0 ------> SPI1_NSS
*/
GPIO_InitStruct.Pin = GPIO_PIN_1|GPIO_PIN_11|GPIO_PIN_12;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF5_SPI1;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_0;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF5_SPI1;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
// DMA
/* DMA controller clock enable */
__HAL_RCC_DMA1_CLK_ENABLE();
/* SPI1 DMA Init */
/* SPI1_RX Init */
hdma_spi_rx.Instance = DMA1_Channel2;
hdma_spi_rx.Init.Request = DMA_REQUEST_1;
hdma_spi_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_spi_rx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_spi_rx.Init.MemInc = DMA_MINC_ENABLE;
hdma_spi_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_spi_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_spi_rx.Init.Mode = DMA_NORMAL;
hdma_spi_rx.Init.Priority = DMA_PRIORITY_LOW;
if (HAL_DMA_Init(&hdma_spi_rx) != HAL_OK) return false;
__HAL_LINKDMA(&hspi,hdmarx,hdma_spi_rx);
/* DMA interrupt init */
/* DMA1_Channel2_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA1_Channel2_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA1_Channel2_IRQn);
/* SPI1 DMA Init */
/* SPI1_TX Init */
hdma_spi_tx.Instance = DMA1_Channel3;
hdma_spi_tx.Init.Request = DMA_REQUEST_1;
hdma_spi_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
hdma_spi_tx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_spi_tx.Init.MemInc = DMA_MINC_ENABLE;
hdma_spi_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_spi_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_spi_tx.Init.Mode = DMA_NORMAL;
hdma_spi_tx.Init.Priority = DMA_PRIORITY_LOW;
if (HAL_DMA_Init(&hdma_spi_tx) != HAL_OK) return false;
__HAL_LINKDMA(&hspi,hdmatx,hdma_spi_tx);
/* DMA interrupt init */
/* DMA1_Channel3_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA1_Channel3_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA1_Channel3_IRQn);
And this is the code that runs on the master:
unsigned int bitsPerByte = 8u;
unsigned int delay = 0u;
unsigned int speed = 100; // hz
unsigned int cs_change = 0u; // false in C
// initialization
fd = ::open("/dev/spidev0.0", O_RDWR);
auto mode = SPI_MODE_2; // clock polarity low, clock phase second edge
if (fd == -1)
throw std::runtime_error("Can't open the spi device");
if (::ioctl(fd, SPI_IOC_WR_MODE, &mode) == -1)
throw std::runtime_error("Can't set the spi mode");
/*
* bits per word
*/
auto bits = bitsPerByte;
auto ret = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits);
if (ret == -1)
throw std::runtime_error("can't set bits per word");
ret = ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &bits);
if (ret == -1)
throw std::runtime_error("can't get bits per word");
/*
* max speed hz
*/
auto maxSpeed = speed;
ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &maxSpeed);
if (ret == -1)
throw std::runtime_error("can't set max speed hz");
ret = ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &maxSpeed);
if (ret == -1)
throw std::runtime_error("can't get max speed hz");
// code used for sending messages
void transfer(uint8_t *tx, uint8_t *rx, size_t size) {
struct spi_ioc_transfer tr = {
(unsigned long)tx, // .tx_buf
(unsigned long)rx, // .rx_buf
size, // .len
speed, // .speed_hz
delay, // .delay_usecs
bitsPerByte, // .bits_per_word
cs_change, // .cs_change
0, // .tx_nbits
0, // .rx_nbits
0, // .pad
};
if (::ioctl(fd, SPI_IOC_MESSAGE(1), &tr) == -1)
throw std::runtime_error("Can't send data throught the spi");
}
In the main functions of the slaves the only thing that I actually do is to send back the exact packet that I receive.
EDIT
On the forum of the Raspberry someone told me to use piscope to see the digital value that is send on the pins. I've done it and I've seen that the CE0 and CE1 pin are always low. I can't understand why I do not have collisions on the MISO.
EDIT 2
I've solved the second problem (the duplicated data) it was an error on the master configuration, I was using cs_change = 1 but it must be equal to 0.
With piscope I've figured out that the slaves are sending the data correctly, it's the master that does not read them well.
I'm trying to understand initializing an ADC on the ARM Cortex M4 MK20DX256VLH7 on the Teensy 3.1. I'm curious about the terminology and relevant search terms as to what the symbols below mean. &= ~(3<<18), which I interpret as a bitwise AND on a bitwise NOT(3 bitwise left shift 18), means very little to me. I interpret what is inside the parenthetical as BIN 11 shifts to BIN 11000000000000000000. I understand that there is a pointer dereference happening to PINMODE1 (which is a little fuzzy to me) and that it is initializing pin 25 on the chip as an ADC input? I am not at all confident in my ability to parse this. Please advise. Thank you for your time.
void ADC_Init (void) {
LPC_PINCON->PINMODE1 &= ~(3<<18); /* P0.25 */
LPC_PINCON->PINMODE1 |= (1<<18); /* has neither pull-up nor pull-down */
LPC_PINCON->PINSEL1 &= ~(3<<18); /* P0.25 is GPIO */
LPC_PINCON->PINSEL1 |= (1<<18); /* P0.25 is AD0.2 */
LPC_SC->PCONP |= (1<<12); /* Enable power to ADC block */
LPC_ADC->ADCR = (1<< 2) | /* select AD0.2 pin */
(4<< 8) | /* ADC clock is 25MHz/5 */
(1<<16) | /* Burst mode */
(1<<21); /* enable ADC */
// LPC_ADC->ADINTEN = (1<< 8); /* global enable interrupt */
// NVIC_EnableIRQ(ADC_IRQn); /* enable ADC Interrupt */
}