Продолжаем тему программирования контроллера STM32F4 и также продолжаем работу с последовательной FLASH-памятью серии W25Q. И теперь мы попробуем считать из микросхемы для начала служебную информацию, но уже не с использованием стандартной терминальной программы, а с помощью программы, которую я начал писать сам. Дело в том, что с помощью терминальной программы тяжело общаться с контроллером в плане передачи различных команд, а также и неудобно.
Программу можно будет скачать по ссылке внизу страницы. Чтобы воспользоваться данной программой, нужно будет также немного модифицировать наш код.
Схема наша осталась такая же, как и в прошлом уроке
Проект за основу мы возьмём также из прошлого урока с именем SPI_25Q32_READ и назовём его SPI_25Q32_INFO_TO_PC.
Только сейчас мы воспользуемся старым добрым Кейлом, поэтому запустим наш проект в Cube MX и внесём соответствующие изменения в настройках
Также включим на выход ножки, отвечающие за свечение светодиодов
Больше ничего не меняем, сгенерируем проект и откроем его в Keil.
На всякий случай соберём проект и прошьём контроллер, чтобы проверить, не пропала ли работоспособность из за смены IDE.
В файле w25q_spi.h объявим следующую функцию, а то в прошлом уроке не добавили
1 2 |
void W25_Read_Data(uint32_t addr, uint8_t* data, uint32_t sz); void W25_Read_Page(uint8_t* data, uint32_t page_addr, uint32_t offset, uint32_t sz); |
В функции main() файла main.c удалим объявление переменной и массива
char str1[30];
unsigned int addr=0;
Объявим небольшой массив
1 2 |
/* USER CODE BEGIN 1 */ uint8_t dt1[10]; |
Код после вызова функции W25_Ini до бесконечного цикла удалим.
В качестве запрос информации о микросхеме компьютерная программа будет передавать байт с числом 33. Примем байт и узнаем, то ли это число, в бесконечном цикле. Если это 33, то зажжём зелёный светодиод
1 2 3 4 5 6 |
/* USER CODE BEGIN 3 */ HAL_UART_Receive(&huart1,(uint8_t*)dt1,1,0x10); if(dt1[0] == 33) { HAL_GPIO_WritePin(GPIOG, GPIO_PIN_13, GPIO_PIN_SET); } |
В файле w25q_spi.c после функции W25_Reset добавим функцию для сбора информации из микросхемы в буфер. Подобный код был в функции инициализации, только он данную информацию отправлял сразу в порт
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 |
//------------------------------------------------------------- void W25_Read_Info(char* str_info) { unsigned int id = W25_Read_ID(); sprintf(str_info,"ID:0x%X\n",id); id &= 0x0000ffff; w25_info.high_cap = 0; switch(id) { case 0x401A: w25_info.high_cap=1; w25_info.BlockCount=1024; strcat(str_info,"w25qxx Chip: w25q512\n"); break; case 0x4019: w25_info.high_cap=1; w25_info.BlockCount=512; strcat(str_info,"w25qxx Chip: w25q256\n"); break; case 0x4018: w25_info.BlockCount=256; strcat(str_info,"w25qxx Chip: w25q128\n"); break; case 0x4017: w25_info.BlockCount=128; strcat(str_info,"w25qxx Chip: w25q64\n"); break; case 0x4016: w25_info.BlockCount=64; strcat(str_info,"w25qxx Chip: w25q32\n"); break; case 0x4015: w25_info.BlockCount=32; strcat(str_info,"w25qxx Chip: w25q16\n"); break; case 0x4014: w25_info.BlockCount=16; strcat(str_info,"w25qxx Chip: w25q80\n"); break; case 0x4013: w25_info.BlockCount=8; strcat(str_info,"w25qxx Chip: w25q40\n"); break; case 0x4012: w25_info.BlockCount=4; strcat(str_info,"w25qxx Chip: w25q20\n"); break; case 0x4011: w25_info.BlockCount=2; strcat(str_info,"w25qxx Chip: w25q10\n"); break; default: strcat(str_info,"w25qxx Unknown ID\n"); return; } w25_info.PageSize=256; w25_info.SectorSize=0x1000; w25_info.SectorCount=w25_info.BlockCount*16; w25_info.PageCount=(w25_info.SectorCount*w25_info.SectorSize)/w25_info.PageSize; w25_info.BlockSize=w25_info.SectorSize*16; w25_info.NumKB=(w25_info.SectorCount*w25_info.SectorSize)/1024; sprintf(str1,"Page Size: %d Bytes\n",(unsigned int)w25_info.PageSize); strcat(str_info,str1); sprintf(str1,"Page Count: %u\n",(unsigned int)w25_info.PageCount); strcat(str_info,str1); sprintf(str1,"Sector Size: %u Bytes\n",(unsigned int)w25_info.SectorSize); strcat(str_info,str1); sprintf(str1,"Sector Count: %u\r\n",(unsigned int)w25_info.SectorCount); strcat(str_info,str1); sprintf(str1,"Block Size: %u Bytes\n",(unsigned int)w25_info.BlockSize); strcat(str_info,str1); sprintf(str1,"Block Count: %u\n",(unsigned int)w25_info.BlockCount); strcat(str_info,str1); sprintf(str1,"Capacity: %u KB\n",(unsigned int)w25_info.NumKB); strcat(str_info,str1); } //------------------------------------------------------------- |
Добавим прототип данной функции в файле w25q_spi.h
1 2 |
void W25_Reset (void); void W25_Read_Info(char* str_info); |
Вернёмся в файл w25q_spi.c и в функции инициализации W25_Ini уберём всё лишнее. Останется только вот это
1 2 3 4 5 6 |
void W25_Ini(void) { HAL_Delay(100); W25_Reset(); HAL_Delay(100); } |
Вернёмся в файл main.c в бесконечный цикл и, используя написанную нами функцию, заберём информацию о микросхеме в буфер
1 2 |
HAL_GPIO_WritePin(GPIOG, GPIO_PIN_13, GPIO_PIN_SET); W25_Read_Info((char*)&rx_buf); |
Чтобы компьютерной программе распознать, что от нашего контроллера придёт служебная информация о микросхеме, в самом первом байте он будет ждать от нас число 5. Поэтому занесём его в начало нашего буфера
1 2 3 |
W25_Read_Info((char*)&rx_buf); //05 - info dt1[0] = 0x05; |
в следующие 4 байта добавим число, равное длине нашего служебного сообщения, чтобы компьютер знал, сколько байтов ему принимать
1 2 |
dt1[0] = 0x05; *(unsigned int*)(dt1+1) = strlen((char*)rx_buf); |
Передадим наши 5 байтов
1 2 |
*(unsigned int*)(dt1+1) = strlen((char*)rx_buf); HAL_UART_Transmit(&huart1,(uint8_t*)dt1,5,0x1000); |
А после этого передадим наш строковый буфер компьютеру
1 2 |
HAL_UART_Transmit(&huart1,(uint8_t*)dt1,5,0x1000); HAL_UART_Transmit(&huart1,rx_buf,strlen((char*)rx_buf),0x1000); |
Выйдем из тела условия, обнулим первый байт в буфере, чтобы не попадать туда каждый раз в бесконечном цикле и добавим небольшую задержку
1 2 3 4 |
HAL_UART_Transmit(&huart1,rx_buf,strlen((char*)rx_buf),0x1000); } dt1[0] = 0; HAL_Delay(1); |
Ну вот и всё. Осталось проверить, как это всё будет работать.
Соберём код, прошьём контроллер, запустим программу и нажмём кнопку Info, после чего мы должны получить что-то типа вот этого
Ну вот. Теперь можно будет развивать проект.
Всем спасибо за внимание!
Предыдущий урок Программирование МК STM32 Следующий урок
Программа для работы с микросхемой
Отладочную плату можно приобрести здесь STM32F429I-DISCO
Микросхему FLASH-памяти W25Q32FVSSIG SOP8 (10 штук) можно приобрести здесь W25Q32FVSSIG
Смотреть ВИДЕОУРОК в RuTube (нажмите на картинку)
Смотреть ВИДЕОУРОК в YouTube (нажмите на картинку)
Здорово! С возвращением! Спвсибо.
Здоровья, здоровья и еще раз здоровья!!!
Здравствуйте.
Скажите пожалуйста, где объявлен буфер — rx_buf
И почему он передаётся вторым аргументом(ниже) иммено так?
HAL_UART_Transmit(&huart1, rx_buf, strlen((char*)rx_buf), 0x1000);
CubIDE ругается — pointer targets in passing argument 2 differ in signedness.