2019-07-27 05:16 PM
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){
}
// *******************************************************
}
// ***********************************************************
2019-07-27 08:20 PM
Your code looks basically okay -- very similar to what I'm doing on an STM32F767ZI. Without going through every line, and checking the magic numbers (hard-coded numerical hexadecimal constants) there's two things that look suspicious:
SPI3->CR1 |=0x31; // Configuracion del BaudRate as 256
The baud rate is set in bits 3 through 5 of the CR1 register. The above code might not be a problem, but you are setting BR to 0b110 and then also the CPHA bit with "0x31". You probably want to do a "<< 3" of the value to put the bits in the correct position (and also have only 3 bits).
Also, these bits are a divisor of the APB1 clock, which is in turn driven by the main SYSCLK. You aren't doing any explicit RCC clock configuration, so check to make sure you're getting what you want. But in any case the MAX7219 probably isn't picky about baud rate (within some limits) so this might not be a problem. You are setting and clearing many bits, including ones that are by default what you want, in CR1 and CR2 (using many excessive multiple writes), so check that all of them are exactly what you want.
More importantly, you're not explicitly setting the SPI data size via the CR2->DS bits. They should be 8 bits (0b0111) by default, but see https://community.st.com/s/question/0D50X0000AxCESNSQ4/i-have-problem-to-set-up-8-data-bit-serial-peripheral-interface-when-i-set-data-bit-size-8-i-have-8-proper-data-bits-and-16-clocks-in-transmit-mode-how-could-it-be-fixed and related posts about the craziest of all STM crazy implementations whereby things other than this value influence the true data size.
I hope some of this helps, and thanks for your post. I learned a little bit of Spanish using Google Translate to understand the code. :)
2019-07-28 05:47 AM
You opened the documentation, and read it - this is a good deed. You do not have enough examples, this problem can be solved.
1 When writing to the register of many small constants - it makes sense to collect all the constants in one record. In this case there will be one write operation, instead of a set of separate ones.
2 If a constant is not used, or its value is zero, there is no point in using it at the given place of assignment.
3 Numeric constants with a range greater than one are written in _VAL2FLD (field, value). This macro reduces numeric input errors to zero damage to the other constants.
4 Data registers have a fixed size, but may accept smaller data. For this it is necessary to show the program the new size of the data register. uint8_t * tmp; tmp = & SPI1-> DR; * tmp = reg;
Below is a sample code for st7735, just an example.
RCC->APB2ENR |= RCC_APB2ENR_SPI1EN;
SPI1->CR1 = 0x0;
SPI1->CR2 = SPI_CR2_SSOE | // NSS pin - control output
_VAL2FLD(SPI_CR2_DS, 7 ) | // Data size 8bit
SPI_CR2_NSSP; // NSS pulse management
SPI1->CR1 = _VAL2FLD(SPI_CR1_BR, 1)| // Baud rate control (PCLK2/4) 27MGz
SPI_CR1_MSTR | // Master mode
SPI_CR1_BIDIMODE | // 1 line
SPI_CR1_BIDIOE | // only transfer
SPI_CR1_SPE; // on
#define st7735_com_en GPIOC->BSRR = 1<<(4+16)
#define st7735_com_of GPIOC->BSRR = 1<<(4)
void st7735_comand (uint8_t reg){
while((SPI1->SR &(SPI_SR_BSY | SPI_SR_TXE)) != SPI_SR_TXE);
st7735_com_en;
uint8_t *tmp; tmp = &SPI1->DR; *tmp = reg;
while(SPI1->SR &SPI_SR_BSY);
st7735_com_of;
};
void st7735_data (uint8_t reg){
while((SPI1->SR &(SPI_SR_BSY | SPI_SR_TXE)) != SPI_SR_TXE);
uint8_t *tmp; tmp = &SPI1->DR; *tmp = reg;
};
2019-07-28 07:29 PM
Hi thanks4opensource, thanks for answer me. I see that you are right about the baud rate, my hex are wrong, i fixed it and prove but doesn't correctly run. i mean, i use my send funtion and in the debugger on Tx Fifo i look that isn't the same. ( i adjunt the photo of the debugger) . if you see, i send 2 bytes, 0x04 and 0x00, in the right i see the state of the register, and Tx Fifo should be the same with the information that i send but it's too different.
you said about the RCC register, i only turn on the SPI3 clock with the RCC->APB1ENR, if you refer to another please can you said me what it is? and the last, can you sow me communication code ? is only for check the irregular things
2019-07-28 10:07 PM
A few things ...
Try this and see if it helps. I still think your code is basically correct.