This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

HI everyone, i'm trying to do an a SPI communication between the board STM32F746 and the MAX7219 to controller a matrix. i'm working in keil uvision 5 and programming without libraries, DMA, CMSIS or other. i programm through registers putting &

HI everyone, i'm trying to do an a SPI communication between the board STM32F746 and the MAX7219 to controller a matrix. i'm working in keil uvision 5 and programming without libraries, DMA, CMSIS or other. i programm through registers putting '1'. i want a full-duplex communication, as slave and onliy are one slave. i add the code that i do. it's on spanish that is my languaje. i hope that all can understand me and solve this. thanks

// Code

/*

Pines:

PB3: SCL

PB4: MISO 

PB5: MOSI 

*/

// ************************ LIBRERIAS ************************

#include <stdio.h>

#include "STM32F7xx.h"

// ***********************************************************

// ************************ VARIABLES GLOBALES ***************

// ***********************************************************

// ************************ FUNCIONES ************************

void enviar_datos(char comando, char dato){

char recibido=0;

// Espera mientras la busy flag esta activa

while(!(SPI3->SR & SPI_SR_TXE)){} // Mientas la busy flago esta en 1 no se

SPI3->DR=comando; //

while(SPI3->SR & SPI_SR_RXNE){} // Tiempo de espera mientras se vacia el buffer

recibido=SPI3->DR;

while(!(SPI3->SR & SPI_SR_TXE)){} // Mientas la busy flago esta en 1 no se puede tr

SPI3->DR=dato; //

while(SPI3->SR & SPI_SR_RXNE){} // Tiempo de espera mientras se vacia el buffer

recibido=SPI3->DR;

}

char leer_datos(char direccion){

char recibido=0;

// Espera mientras la busy flag esta activa

while(!(SPI3->SR & SPI_SR_TXE)){} // Mientas la busy flago esta en 1 no se puede

SPI3->DR=direccion; //

while(SPI3->SR & SPI_SR_RXNE){} // Tiempo de espera mientras se vacia el buffer

recibido=SPI3->DR;

while(!(SPI3->SR & SPI_SR_TXE)){} // Mientas la busy flago esta en 1 no se puede

SPI3->DR=0x00; //

while(SPI3->SR & SPI_SR_RXNE){} // Tiempo de espera mientras se vacia el buffer

return SPI3->DR; 

}

// ***********************************************************

// ************************ INTERRUPCIONES *******************

extern "C"{

}

// ***********************************************************

// ************************ MAIN *****************************

int main(void){

// ******************** PUERTOS **************************

RCC->AHB1ENR |=0x03; // Activo el puerto A y B

// *******************************************************

// ******************** PINES ****************************

GPIOA->MODER |=0x80000000; // Alternativo pin 15

GPIOA->AFR[1] =0x60000000; // Funcion alterna 6

GPIOB->MODER |=0xA80; // Alternativo pines 3 a 5 

GPIOB->AFR[0] =0x666000; // Funcion alterna 6 

// *******************************************************

// ******************** SPI ******************************

RCC->APB1ENR |=RCC_APB1ENR_SPI3EN; // Activo el Habilitador del SPI 3

SPI3->CR1 |=0x31; // Configuracion del BaudRate as 256

SPI3->CR1 |=SPI_CR1_CPHA; // Configuracion de la fase del SLC, la he

SPI3->CR1 |=SPI_CR1_CPOL; // Configuracion de la polaridad del Reloj,

SPI3->CR1 |=SPI_CR1_SSM; // Activo el asistente de slave select

SPI3->CR1 &=~SPI_CR1_RXONLY; // Configuracion para que la Full-duplex

SPI3->CR1 &=~SPI_CR1_BIDIMODE; // Configuracion para tener 2 lineas

SPI3->CR1 &=~SPI_CR1_LSBFIRST; // Configuracion para que se transmita

SPI3->CR1 |=SPI_CR1_CRCEN; // No necesito CRC

SPI3->CR1 |=SPI_CR1_MSTR; // Configuracion del SPI como MASTER

SPI3->CR1 |=SPI_CR1_SSI; 

SPI3->CR1 &=~SPI_CR1_CRCL; // tamaño de 8 bits

// CR2

SPI3->CR2 |=0x700; // Configuracion del tamaño de la informacion a

SPI3->CR2 |=SPI_CR2_SSOE; // Activo el output SS para tener un unico

SPI3->CR2 &=~SPI_CR2_FRF; // SPI en modo normal 

SPI3->CR2 &=~SPI_CR2_NSSP; // No deseo pulsos en la linea SS

SPI3->CR2 |=SPI_CR2_FRXTH; // Se activa la interrupcion Rx si recibe 8 bits

SPI3->CR1 |=SPI_CR1_SPE; // Activo el periferico 

enviar_datos(0x04,0x00);

// *******************************************************

// ******************** MAIN *****************************

while(true){

}

// *******************************************************

}

// ***********************************************************

  • Please don't put the whole question in the title!

    i hope that all can understand me and solve this

    Solve what, exactly ?

    You haven't said what problem(s) you're having!

    Standard questions:

    1. What did you intend to happen?
    2. What is actually happening?
    3. What investigation / testing / debugging have you done to find the problem(s) ?

    How To Debug

  • Yes to what Andy said. It is not at all clear what is not working properly. (What you expect to happen and what is actually happening.)

    1) Read the Data Sheet.

    2) Understand what state the chip is in after initial power up.

    3) This is a write only part.  You cannot read any data from it.  You can check the RX data for understanding clocking, but the data will be meaningless.

    4) You need another pin to "Load" the data.  Chip select can be used as long as you understand that it loads the last 16-bit sent to the chip on the rising edge of the LOAD line.

    5) Make sure your data has been fully clocked out before asserting the LOAD line.  It looks like you are trying to do that by waiting for RX_RDY, but I have know people who thought we can just file TX

    5) You might find it easier to configure 3 pins as GPIO output and bit bang the data out.

    6) I don't see anything for sure wrong with your SPI driver save you are not using the Chip select.  

    7) The best command to send first is the Display Test Command.  This command can be sent with the chip in any state and will turn on all items.  

         

    enviar_datos(0x0F,0x01);   // Turns on all items in the MATRIX, no matter what state the chip is in.   Get this to work and you will be good.

    enviar_datos(0x0F,0x00):  // This will return to the state that the chip was in before the Display test was sent.

  • HI, i'm sorry for put all the question in the title, i answer all of yours questions:

    1.  When i prove the code in the keil debugger, i hope that the registers TXFifo is the same like a transmit data in my function. I mean, if i send for example 0x08 (1 byte), in the TXFifo show 0x08, but this doesn't happen, if i send for example the same 0x08 in the tx fifo i se ... 0x1A doesn't match and i dont kwno why happens 
    2. this that i told you, the TxFifo doesnt match with the data transmit 

    3. the proof is the debugger, i show you an a debugger photo: 

    i send two bytes and in the debugger doesn't match. i don't know what is could be wrong, i thing that is the transmit function because the spi configuration are based on the datasheet.

  • It is common that you cannot read-back a Tx register:

    These are not memory locations, they are "gateways" into the hardware:

    • When you write, you send stuff to the transmitter;
    • When you read, you receive stuff from the receiver.

    As   said, you need to study the datasheet to understand how this works in your particular chip.

    the proof is the debugger

    No. 

    The proof is to use an oscilloscope or analyser to see what is actually happening on the actual hardware lines.

  • Hi, 

    If you haven't looked at it yet, I'd suggest using the SPI CMSIS-Driver that ST and Keil have in the latest ST32F7 pack: 

    - If you go to:http://www.keil.com/dd2/pack/#Keil.STM32F7xx_DFP

    - and expand the "STMicroelectronics STM32F7 Series Device Support, Drivers and Examples" section, you can download version 2.12.0. From that description, I see they improved the functionality of the SPI code. 

    - Once you have that update installed, you can add the open the Manage RTE window:

    http://www.keil.com/support/man/docs/uv4/uv4_ca_rtemanager.htm

    - Expand the "CMSIS driver" software component, and check the box next to SPI. You might have to hit the resolve button on the bottom. 

    You can read about the SPI functions here:

    http://www.keil.com/pack/doc/CMSIS/Driver/html/group__spi__interface__gr.html