Еще при записи памяти теряются несколько первых байт, остальные записываются нормально.
Настройки порта
Код
RCC->APB2ENR |= RCC_APB2ENR_SPI1EN; //SPI1 clock
RCC->APB2ENR |= RCC_APB2ENR_AFIOEN; //включить тактирование альтернативных функций /
RCC->APB2ENR |= RCC_APB2ENR_IOPAEN; //включить тактирование порта А
//вывод SCK: выход двухтактный, альтернативная функция, 50MHz
GPIOA->CRL |= GPIO_CRL_MODE5; //
GPIOA->CRL &= ~GPIO_CRL_CNF5; //
GPIOA->CRL |= GPIO_CRL_CNF5_1; //
//вывод MISO: вход цифровой с подтягивающим резистором, подтяжка к плюсу
GPIOA->CRL &= ~GPIO_CRL_MODE6; //
GPIOA->CRL &= ~GPIO_CRL_CNF6; //
GPIOA->CRL |= GPIO_CRL_CNF6_1; //
GPIOA->BSRR = GPIO_BSRR_BS6; //
//вывод MOSI: выход двухтактный, альтернативная функция, 50MHz
GPIOA->CRL |= GPIO_CRL_MODE7; //
GPIOA->CRL &= ~GPIO_CRL_CNF7; //
GPIOA->CRL |= GPIO_CRL_CNF7_1; //
RCC->APB2ENR |= RCC_APB2ENR_SPI1EN; //подать тактирование /
SPI1->CR1 = 0x0000; //очистить первый управляющий регистр
SPI1->CR2 = 0x0000; //очистить второй управляющий регистр
SPI1->CR1 |= SPI_CR1_MSTR; //контроллер должен быть мастером
SPI1->CR1 |= SPI_CR1_BR; //задаем скорость
//SPI1->CR1 |= SPI_CR1_BR_0; //задаем скорость
//SPI1->CR1 |= SPI_CR1_BR_1; //задаем скорость
//SPI1->CR1 |= SPI_CR1_BR_2; //задаем скорость
SPI1->CR1 |= SPI_CR1_CPOL;
SPI1->CR1 |= SPI_CR1_CPHA;
SPI1->CR1 |= SPI_CR1_SSI; //обеспечить высокий уровень программного NSS
SPI1->CR1 |= SPI_CR1_SSM; //разрешить программное формирование NSS
SPI1->CR1 |= SPI_CR1_SPE; //разрешить работу модуля SPI
RCC->APB2ENR |= RCC_APB2ENR_AFIOEN; //включить тактирование альтернативных функций /
RCC->APB2ENR |= RCC_APB2ENR_IOPAEN; //включить тактирование порта А
//вывод SCK: выход двухтактный, альтернативная функция, 50MHz
GPIOA->CRL |= GPIO_CRL_MODE5; //
GPIOA->CRL &= ~GPIO_CRL_CNF5; //
GPIOA->CRL |= GPIO_CRL_CNF5_1; //
//вывод MISO: вход цифровой с подтягивающим резистором, подтяжка к плюсу
GPIOA->CRL &= ~GPIO_CRL_MODE6; //
GPIOA->CRL &= ~GPIO_CRL_CNF6; //
GPIOA->CRL |= GPIO_CRL_CNF6_1; //
GPIOA->BSRR = GPIO_BSRR_BS6; //
//вывод MOSI: выход двухтактный, альтернативная функция, 50MHz
GPIOA->CRL |= GPIO_CRL_MODE7; //
GPIOA->CRL &= ~GPIO_CRL_CNF7; //
GPIOA->CRL |= GPIO_CRL_CNF7_1; //
RCC->APB2ENR |= RCC_APB2ENR_SPI1EN; //подать тактирование /
SPI1->CR1 = 0x0000; //очистить первый управляющий регистр
SPI1->CR2 = 0x0000; //очистить второй управляющий регистр
SPI1->CR1 |= SPI_CR1_MSTR; //контроллер должен быть мастером
SPI1->CR1 |= SPI_CR1_BR; //задаем скорость
//SPI1->CR1 |= SPI_CR1_BR_0; //задаем скорость
//SPI1->CR1 |= SPI_CR1_BR_1; //задаем скорость
//SPI1->CR1 |= SPI_CR1_BR_2; //задаем скорость
SPI1->CR1 |= SPI_CR1_CPOL;
SPI1->CR1 |= SPI_CR1_CPHA;
SPI1->CR1 |= SPI_CR1_SSI; //обеспечить высокий уровень программного NSS
SPI1->CR1 |= SPI_CR1_SSM; //разрешить программное формирование NSS
SPI1->CR1 |= SPI_CR1_SPE; //разрешить работу модуля SPI
Скорость самая маленькая. С битами SPI_CR1_CPOL и SPI_CR1_CPHA баловался, результат тотже.
Процедуры чтения и записи
Код
void send_spi1_byte(unsigned char byte)
{
while ((SPI1->SR & SPI_SR_TXE) == 0);
SPI1->DR = byte;
}
unsigned char read_spi1_byte(void)
{
unsigned char byte;
send_spi1_byte(0xFF);
while ((SPI1->SR & SPI_SR_RXNE) == 0);
byte = SPI1->DR;
return byte;
}
{
while ((SPI1->SR & SPI_SR_TXE) == 0);
SPI1->DR = byte;
}
unsigned char read_spi1_byte(void)
{
unsigned char byte;
send_spi1_byte(0xFF);
while ((SPI1->SR & SPI_SR_RXNE) == 0);
byte = SPI1->DR;
return byte;
}
Сама функция Manufacturer and Device ID Information
Код
void at45_devid(void)
{
volatile unsigned int i;
cs_spi1_low();
send_spi1_byte(0x9F);
for(i = 0;i < 6;i++)
{
at45_read_buf[i] = read_spi1_byte();
}
cs_spi1_high();
}
{
volatile unsigned int i;
cs_spi1_low();
send_spi1_byte(0x9F);
for(i = 0;i < 6;i++)
{
at45_read_buf[i] = read_spi1_byte();
}
cs_spi1_high();
}