stm32f103 помогите настроить spi или порт кода с дуины

Кто любит RISC в жизни, заходим, не стесняемся.
Ответить
fsmoke
Грызет канифоль
Сообщения: 275
Зарегистрирован: Сб июл 10, 2010 19:33:15

stm32f103 помогите настроить spi или порт кода с дуины

Сообщение fsmoke »

Короче есть старинные джойстики от sp1. Хочу читать их stmкой. Начитался реверс доков - короче это spi (ну и протокол свой поверх).

Для быстрой проверки не дохлый ли джойстик накачал библиотек разных для дуины и начал смотреть - ну как обычно ничего не завелось. И просидев 2 дня - я таки нашел какой-то пример с какой-то библиотекой из 2х строк - и вуаля джойстик ответил. В общем поигрался и начал перетаскивать это на стм. Естественно на г..нодуине - это всё написано было софтверно никакого аппаратного spi.

на stmке врубил spi1 и начал - но нихрена не выходит - и да.... это мой первый проект на стм - с целью обучения в общем

сам spi работает - делаю петлю miso и mosi вызываю HAL_SPI_TransmitReceive - всё гуд - что уходит то и приходит.

провозившись порядочно - решил портировать код с дуины - портировал, всё работает(ток задержки поправил - видимо стм слишком резвый ).

код порта:

Код: Выделить всё

extern uint32_t SystemCoreClock;
 
void DWT_Init(void) 
{
	if (!(CoreDebug->DEMCR & CoreDebug_DEMCR_TRCENA_Msk)) 
	{
		CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
		DWT->CYCCNT = 0;
		DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;
	}
}
 
uint32_t DWT_Get(void)
{
	return DWT->CYCCNT;
}
 
static inline uint8_t DWT_Compare(int32_t tp)
{
	return (((int32_t)DWT_Get() - tp) < 0);
}
 
void DWT_Delay(uint32_t us) // microseconds
{
	int32_t tp = DWT_Get() + us * (SystemCoreClock / 1000000);
	while (DWT_Compare(tp)) ;
}

#define DAT_Pin_PORT GPIOB
#define DAT_Pin GPIO_PIN_14
#define CLK_Pin_PORT GPIOB
#define CLK_Pin GPIO_PIN_13
#define CMD_Pin_PORT GPIOB
#define CMD_Pin GPIO_PIN_12

uint8_t _shift(uint8_t _dataOut)							// Does the actual shifting, both in and out simultaneously
{
	GPIO_PinState _temp = 0;
	uint8_t _dataIn = 0;

	for (uint8_t _i = 0; _i <= 7; _i++)
	{
		
		
		if (_dataOut & (1 << _i)) 
			HAL_GPIO_WritePin(CMD_Pin_PORT, CMD_Pin, GPIO_PIN_SET);
		else 
			HAL_GPIO_WritePin(CMD_Pin_PORT, CMD_Pin, GPIO_PIN_RESET);

		HAL_GPIO_WritePin(CLK_Pin_PORT, CLK_Pin, GPIO_PIN_RESET);
		
		DWT_Delay(30);

		_temp = HAL_GPIO_ReadPin(DAT_Pin_PORT, DAT_Pin);
		
		if (_temp == GPIO_PIN_SET)
		{
			_dataIn = _dataIn | (0x80 >> _i); 		// Shifts the read data into _dataIn
		}

		HAL_GPIO_WritePin(CLK_Pin_PORT, CLK_Pin, GPIO_PIN_SET);
		DWT_Delay(30);
	}
	return _dataIn;
}

unsigned int read_gp()
{
	HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_RESET);

	_shift(0x01);
	_shift(0x42);
	_shift(0x00);

	uint8_t _data1 = ~_shift(0xFF);
	uint8_t _data2 = ~_shift(0xFF);

	HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_SET);

	unsigned int _dataOut = (_data2 << 8) | _data1;

	return _dataOut;
} 

Сама команда как вы уже догадались 0x01,0x42,0x00,0xff,0xff

при запихивании её в HAL_SPI_TransmitReceive - на выходе мусор

Теперь немного о протоколе(мой перевод кусков):

1)допустимая частота от 100kHz до 500kHz - я пробовал и ~230 и ~140 (делителями SPI и APB2) - болт
2)Нога частоты в высоком уровне до тех пор пока не будут передаваться байты. Она становится в низкий уровень для начала 8 циклов во время которых данные одновременно передаются и принимаются.
2)байты передаются как LSB (least significant bit) первым, таким образом биты слева(раньше во времени) младшие.

Изображение

Как видно с картинки - все сигналы по дефолту высокие.(Лучше картинки нет у них сайт побился)
Attention - это в их терминологии chip select.

Теперь мои настройки SPI:

Код: Выделить всё

static void MX_SPI1_Init(void)
{

  /* SPI1 parameter configuration*/
	hspi1.Instance = SPI1;
	hspi1.Init.Mode = SPI_MODE_MASTER;
	hspi1.Init.Direction = SPI_DIRECTION_2LINES;
	hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
	hspi1.Init.CLKPolarity = SPI_POLARITY_HIGH; 
	hspi1.Init.CLKPhase = SPI_PHASE_1EDGE; 
	hspi1.Init.NSS = SPI_NSS_SOFT;
	hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_256;
	hspi1.Init.FirstBit = SPI_FIRSTBIT_LSB; 
	hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
	hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
	hspi1.Init.CRCPolynomial = 10;
	if (HAL_SPI_Init(&hspi1) != HAL_OK)
	{
	_Error_Handler(__FILE__, __LINE__);
	}

}

void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi)
{

  GPIO_InitTypeDef GPIO_InitStruct;
  if(hspi->Instance==SPI1)
  {
  
    /* Peripheral clock enable */
    __HAL_RCC_SPI1_CLK_ENABLE();
  
    /**SPI1 GPIO Configuration    
    PA5     ------> SPI1_SCK
    PA6     ------> SPI1_MISO
    PA7     ------> SPI1_MOSI 
    */
    GPIO_InitStruct.Pin = GPIO_PIN_5|GPIO_PIN_7;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = GPIO_PIN_6;
    GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);


  }

}
Короче что я менял: поставил SPI_POLARITY_HIGH, SPI_FIRSTBIT_LSB и подтяжку на GPIO_PIN_6.

Без подтяжки не работает ни на дуино.. нигде, в общем нужна тут подтяжка - благо в stm она внутренняя есть

Всё равно приходит мусор - хз что ещё делать - я в тонкостях стм ещё плаваю.

Как мне настроить spi так, чтобы его работа была аналогичной поведению кода софтверного порта (см выше) ?

ПС
Осцилла у меня пока нет - это печально :(
Реклама
Аватара пользователя
Мурик
Друг Кота
Сообщения: 3383
Зарегистрирован: Пн окт 11, 2010 19:00:08

Re: stm32f103 помогите настроить spi или порт кода с дуины

Сообщение Мурик »

fsmoke писал(а):Осцилла у меня пока нет - это печально
В Китае можно купить логический анализатор за 4$.
Реклама
Аватара пользователя
dosikus
Друг Кота
Сообщения: 3604
Зарегистрирован: Пн июл 28, 2008 22:12:01

Re: stm32f103 помогите настроить spi или порт кода с дуины

Сообщение dosikus »

Делал как-то на F1 , джойстик на SPI , USB HID , работало вполне сносно даже в аналоговом режиме.
Все примеры что находил в сети редкостная и гадкая дичь, и даже те что от Рюмика.
fsmoke
Грызет канифоль
Сообщения: 275
Зарегистрирован: Сб июл 10, 2010 19:33:15

Re: stm32f103 помогите настроить spi или порт кода с дуины

Сообщение fsmoke »

[uquote="Мурик",url="/forum/viewtopic.php?p=3475372#p3475372"]
fsmoke писал(а):Осцилла у меня пока нет - это печально
логический анализатор за 4$.[/uquote]

Я знаю - он шел и потерялся по дороге :) - ща буду ещё один заказывать - в любом случае ждать месяц неохота

Добавлено after 2 minutes 31 second:
[uquote="dosikus",url="/forum/viewtopic.php?p=3475382#p3475382"]Делал как-то на F1.[/uquote]

А код остался ? - может можно посмотреть... был бы признателен
Реклама
Эиком - электронные компоненты и радиодетали
Аватара пользователя
dosikus
Друг Кота
Сообщения: 3604
Зарегистрирован: Пн июл 28, 2008 22:12:01

Re: stm32f103 помогите настроить spi или порт кода с дуины

Сообщение dosikus »

Завтра , одно но я не использую калокуб чего и вам желаю...
Реклама
Аватара пользователя
dosikus
Друг Кота
Сообщения: 3604
Зарегистрирован: Пн июл 28, 2008 22:12:01

Re: stm32f103 помогите настроить spi или порт кода с дуины

Сообщение dosikus »

Делал еще в 2014, так что возможны ляпы.
psx.h

Код: Выделить всё

#ifndef _PSX_H
#define _PSX_H
   #include "stm32f10x.h"
  
	
	#define CS_ON GPIOA->BSRR = GPIO_BSRR_BR4  
  #define CS_OFF  GPIOA->BSRR = GPIO_BSRR_BS4
	#define IDLE 0x00                             
   
   
   extern  void Delay_mS(uint32_t );
   void PSx_init(void);
	 void PSx_sw_analog(uint8_t * buffer);
   void PSx_read(uint8_t * buffer);
   
 #endif //_PSX_H
psx.c

Код: Выделить всё

#include"psx.h"


const uint8_t START_seq[]={0x01,0x42,IDLE,0xFF,0xFF};
const uint8_t GONF_seq[]={0x01,0x43,IDLE,0x01,IDLE};
const uint8_t SW_ANALOG_seq[]={0x01,0x44,IDLE,0x01,0x03,IDLE,IDLE,IDLE,IDLE};
const uint8_t EX_GONF_seq[]={0x01,0x43,IDLE,IDLE,IDLE,IDLE,IDLE,IDLE,IDLE};
const uint8_t READ_seq[]={0x01,0x42,IDLE,IDLE,IDLE,IDLE,IDLE,IDLE,IDLE};

void PSx_init(void)
	{
		
	
		RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;	
		RCC->APB2ENR |=RCC_APB2ENR_SPI1EN;
		
	  GPIOA->CRL   &= ~(                    // Clear setting  PA3,PA4,PA5,PA6,PA7
		                   GPIO_CRL_CNF3   |
		                   GPIO_CRL_CNF4   | 
		                   GPIO_CRL_CNF5   | 
		                   GPIO_CRL_CNF6   | 
		                   GPIO_CRL_CNF7   | 
		                   GPIO_CRL_MODE3  |
		                   GPIO_CRL_MODE4  |
		                   GPIO_CRL_MODE5  |
                       GPIO_CRL_MODE6  |		
		                   GPIO_CRL_MODE7
		                    );
		
		GPIOA->CRL   |= ( 
		               GPIO_CRL_CNF3_1   |   // PA3 ACK   IN pullup
		               GPIO_CRL_CNF6_1   | 	 // PA6 MISO  IN pullup
	
		               GPIO_CRL_MODE4    |   // PA4 CS   GP PP 
		
		               GPIO_CRL_CNF5_1   |   // PA5  CLK  AF PP
		               GPIO_CRL_MODE5    |
									 
		               GPIO_CRL_CNF7_1   |   // PA7  MOSI AF PP 
		               GPIO_CRL_MODE7    
		                      );
	
	  GPIOA->ODR   |= 
		               GPIO_ODR_ODR3 |      // pullup PA3& PA6
									 GPIO_ODR_ODR6 
									       ;                     
	 CS_OFF;
	 //-------------------------------------  	                               
	
		SPI1->CR1 |= 
						 SPI_CR1_BR_0 |     // 
						 SPI_CR1_BR_1 | 
						 SPI_CR1_BR_2 | 
						 SPI_CR1_MSTR |
						 SPI_CR1_SSI 	|				 
						 SPI_CR1_SSM  |
						 SPI_CR1_LSBFIRST |
						 SPI_CR1_CPHA     |
						 SPI_CR1_CPOL
						 ;	
	
	
	SPI1->CR1 |= SPI_CR1_SPE;	
	
	
	}
  
 
void PSx_send (const uint8_t * buffer,uint8_t count)
{
				uint8_t i;
				CS_ON;   		// Select  PSx
				Delay_mS(1);
				while(!(SPI1->SR & SPI_SR_TXE)){}   // 
		    SPI1->DR=buffer[0];                    // 
				while(!(SPI1->SR & SPI_SR_RXNE)){}
				(void) SPI1->DR;
					
     for(i=1;i<count;i++)
			{				
		   	while(GPIOA->IDR & 0x08)  {}	
				while(!(GPIOA->IDR &0x08)){}				
				SPI1->DR=buffer[i];                    //
				while(!(SPI1->SR & SPI_SR_RXNE)){}
				(void)  SPI1->DR;				
			}
			//Delay_mS(1);
		  CS_OFF;       // Deselect  PSx  
	    Delay_mS(1);
	    
	
}


	
  
  void PSx_sw_analog(uint8_t * buffer)
  
  {
	  //CS_ON; 
    PSx_send (START_seq,sizeof START_seq);  
    PSx_send (GONF_seq,sizeof GONF_seq);
		PSx_send (SW_ANALOG_seq, sizeof SW_ANALOG_seq);
		PSx_send (EX_GONF_seq, sizeof EX_GONF_seq);
		//CS_OFF; 
  }



 void PSx_read(uint8_t * buffer)
 {
				uint8_t i;
				CS_ON;   		// Select  PSx
				Delay_mS(1);
				while(!(SPI1->SR & SPI_SR_TXE)){}   // 
		
        SPI1->DR=READ_seq[0];                    // 2nd command  
				while(!(SPI1->SR & SPI_SR_RXNE)){}
				(void) SPI1->DR;
			
for(i=1;i<sizeof READ_seq;i++)
			{				
		  	while(GPIOA->IDR & 0x08){}	
				while(!(GPIOA->IDR &0x08)){}					
				SPI1->DR=READ_seq[i];                    // 2nd command  
				while(!(SPI1->SR & SPI_SR_RXNE)){}
				buffer[i]= SPI1->DR;
					
				
			}			
			 
		while((SPI1->SR & SPI_SR_BSY)){}
			
			//	Delay_mS(1); 
		 CS_OFF;	           
	 		Delay_mS(1); 
	 
 }
Реклама
Ответить

Вернуться в «ARM»