STM32F настройка и использование семисегментного LED модуля на чипе MAX7219 с помощью SPL.
Ссылка на видео в YouTubeМикросхема драйвер MAX7219 предназначен для управления индикацией семисегметных LED индикаторов а также LED матрицами. у меня же в статье будем использовать вот такой модуль с восьмью цифрами, передача информации с которым будет осуществляется через интерфейс SPI по шестнадцать бит данных, первым уходит младший байт.
Формат передаваемых данных выглядит следующим образом.
Адресное пространство MAX7219 в котором используется только младших четыре бита.
- No-Op
- не используется, адрес 0.
- Digit 0-Digit 7
- адреса с 1 по 8 для записи отображаемого символа, адрес 1 отображает крайний правый символ, 8 крайний левый.
- Decode Mode
- адрес 9, включение декодирования символов, в данных определяется какой символ должен декодироваться установкой бита в нужную позицию.
Если установить цифрам декодирование то в их адреса для отображения нужного символа необходимо записывать код «B» из таблицы или если не включено то нужно самостоятельно включать нужные сегменты.
- Intensity
- адрес 10, яркость LED.
- Scan Limit
- адрес 11, отображение количества символов, если установить 0 то отображается только первый символ, 1 отображается первый -второй, 2 первый-второй-третий и так далее, 7 отображаются все восемь символов.
- Shutdown
- адрес 12, запись в этот адрес 0 выключит отображение или 1 включит.
- Display Test
- адрес 15, запись в этот адрес 0 выключит тестовый режим, запись 1 включит будут отображается все сегменты.
Практика использования или пример программ.
Для примера я буду использовать контроллер STM32F103C8, SPI в контроллере настроено для отправки сразу 16 бит данных, что бы отправить данные используется функция LCD_Send_Data( uint16_t address, uint16_t data) в которую передаётся адрес регистра MAX7219 и данные которые нужно записать.
Схема подключения.
Первый пример будем отображать символы без декодирования, для этого будет нужен массив символов для включения нужных сигментов.
#include "stm32f10x.h"
#define Decode_Mode 9
#define Intensity 10
#define Scan_Limit 11
#define Shutdown 12
#define Display_Test 15
/*Массив символов 0, 1, 2, 3, 4, 5, 6, 7, 8, 9.*/
const uint16_t CHARACTER[10] = { 126, 48, 109, 121, 51, 91, 95, 112, 127, 123};
void LCD_Send_Data(uint16_t address, uint16_t data);
int main(){
/*Контроллер тактируется от HSI.*/
RCC_DeInit();
/*Настраиваем GPIOВ_Pin_12 для стробирования приёма команд и данных MAX7219.*/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
GPIO_InitTypeDef PIN_Strob;
PIN_Strob.GPIO_Pin = GPIO_Pin_12;
PIN_Strob.GPIO_Speed = GPIO_Speed_10MHz;
PIN_Strob.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOB, &PIN_Strob);
GPIO_SetBits(GPIOB, GPIO_Pin_12);
/*Настраиваем GPIOВ_Pin_13(SPI2_SCK) и GPIOВ_Pin_15(SPI2_MOSI).*/
GPIO_InitTypeDef SPI2_SCK_MOSI;
SPI2_SCK_MOSI.GPIO_Pin = GPIO_Pin_13|GPIO_Pin_15;
SPI2_SCK_MOSI.GPIO_Speed = GPIO_Speed_10MHz;
SPI2_SCK_MOSI.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOB, &SPI2_SCK_MOSI);
/*Настраиваем SPI2 как Master и передачу данных по одной линии.*/
RCC_APB1PeriphClockCmd( RCC_APB1Periph_SPI2, ENABLE);
SPI_InitTypeDef SPI2_InitStructure;
SPI2_InitStructure.SPI_Direction = SPI_Direction_1Line_Tx;
SPI2_InitStructure.SPI_DataSize = SPI_DataSize_16b;
SPI2_InitStructure.SPI_CPOL = SPI_CPOL_Low;
SPI2_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;
SPI2_InitStructure.SPI_NSS = SPI_NSS_Soft;
SPI2_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;
SPI2_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
SPI2_InitStructure.SPI_Mode = SPI_Mode_Master;
SPI_Init(SPI2, &SPI2_InitStructure);
SPI_Cmd(SPI2, ENABLE);
/*Инициализация MAX7219.*/
LCD_Send_Data( Shutdown, 1);
LCD_Send_Data( Display_Test, 0);
LCD_Send_Data( Decode_Mode, 0);
LCD_Send_Data( Intensity, 9);
LCD_Send_Data( Scan_Limit, 7);
while(1){
/*Вывод 7-6-5-4-3-2-1-0.*/
for( uint16_t i=1; i<9; i++){LCD_Send_Data( i, CHARACTER[i-1]);}
for( uint32_t e=0; e<2000000; e++);
/*Вывод 2-3-4-5-6-7-8-9.*/
for( uint16_t i=8; i>0; i--){LCD_Send_Data( i, CHARACTER[10-i]);}
for( uint32_t e=0; e<2000000; e++);
/*Вывод 7-6-5-4-3-2-1-0 с точкой.*/
for( uint16_t i=1; i<9; i++){LCD_Send_Data( i, CHARACTER[i-1] | 128);}//128 маска точки.
for( uint32_t e=0; e<2000000; e++);
}
return 0;
}
/*Функция отправки адреса и данных.*/
void LCD_Send_Data( uint16_t address, uint16_t data){
address<<=8;
address|=data;
GPIO_ResetBits(GPIOB, GPIO_Pin_12);
SPI_I2S_SendData(SPI2, address);
while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_BSY) == SET);
GPIO_SetBits(GPIOB, GPIO_Pin_12);
}
Второй пример здесь включено декодирование всех позиций LED и отсылаем код «B» нужного символа.
#include "stm32f10x.h"
#define Decode_Mode 9
#define Intensity 10
#define Scan_Limit 11
#define Shutdown 12
#define Display_Test 15
void LCD_Send_Data(uint16_t address, uint16_t data);
int main(){
/*Тактируется от HSI.*/
RCC_DeInit();
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
/*Настраиваем GPIOВ_Pin_12 для стробирования приёма команд и данных MAX7219.*/
GPIO_InitTypeDef PIN_Strob;
PIN_Strob.GPIO_Pin = GPIO_Pin_12;
PIN_Strob.GPIO_Speed = GPIO_Speed_10MHz;
PIN_Strob.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOB, &PIN_Strob);
GPIO_SetBits(GPIOB, GPIO_Pin_12);
/*Настраиваем GPIOВ_Pin_13(SPI2_SCK) и GPIOВ_Pin_15(SPI2_MOSI).*/
GPIO_InitTypeDef SPI2_SCK_MOSI;
SPI2_SCK_MOSI.GPIO_Pin = GPIO_Pin_13|GPIO_Pin_15;
SPI2_SCK_MOSI.GPIO_Speed = GPIO_Speed_10MHz;
SPI2_SCK_MOSI.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOB, &SPI2_SCK_MOSI);
/*Настраиваем SPI2 как Master и передачу данных по одной линии.*/
RCC_APB1PeriphClockCmd( RCC_APB1Periph_SPI2, ENABLE);
SPI_InitTypeDef SPI2_InitStructure;
SPI2_InitStructure.SPI_Direction = SPI_Direction_1Line_Tx;
SPI2_InitStructure.SPI_DataSize = SPI_DataSize_16b;
SPI2_InitStructure.SPI_CPOL = SPI_CPOL_Low;
SPI2_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;
SPI2_InitStructure.SPI_NSS = SPI_NSS_Soft;
SPI2_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;
SPI2_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
SPI2_InitStructure.SPI_Mode = SPI_Mode_Master;
SPI_Init(SPI2, &SPI2_InitStructure);
SPI_Cmd(SPI2, ENABLE);
/*Инициализация MAX7219.*/
LCD_Send_Data( Shutdown, 1);
LCD_Send_Data( Display_Test, 0);
LCD_Send_Data( Decode_Mode, 255);
LCD_Send_Data( Intensity, 9);
LCD_Send_Data( Scan_Limit, 7);
while(1){
/*Вывод 7-6-5-4-3-2-1-0.*/
for( uint16_t i=1; i<9; i++){LCD_Send_Data( i, i-1);}
for( uint32_t e=0; e<1000000; e++);
/*Вывод 0-1-2-3-4-5-6-7.*/
for( uint16_t i=8; i>0; i--){LCD_Send_Data( i, 8-i);}
for( uint32_t e=0; e<1000000; e++);
/*Вывод 7-6-5-4-3-2-1-0 с точкой.*/
for( uint16_t i=1; i<9; i++){LCD_Send_Data( i, i-1|128);}
for( uint32_t e=0; e<1000000; e++);
}
return 0;
}
/*Функция отправки адреса и данных.*/
void LCD_Send_Data( uint16_t address, uint16_t data){
address<<=8;
address|=data;
GPIO_ResetBits(GPIOB, GPIO_Pin_12);
SPI_I2S_SendData(SPI2, address);
while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_BSY) == SET);
GPIO_SetBits(GPIOB, GPIO_Pin_12);
}