MCP23S08
PWM na rejestrze przesuwnym można wykonać tak samo jak na każdym dowolnym pinie mikrokontrolera, tzn poprzez cyklicznie załączenie i wyłączanie danego wyprowadzenia. Co do podłączenia to zostało ono zapisane w poście dotyczącym ekspandera portów.
Poniżej inicjalizacja SPI oraz GPIO wraz z funkcjami przesyłającymi dany:
- #include "stm32f10x.h"
- //Deklaracje rejestrów
- #define MCP_IODIR 0x00
- #define MCP_IPOL 0x01
- #define MCP_GPINTEN 0x02
- #define MCP_DEFVAL 0x03
- #define MCP_INTCON 0x04
- #define MCP_IOCON 0x05
- #define MCP_GPPU 0x06
- #define MCP_INTF 0x07
- #define MCP_INTCAP 0x08
- #define MCP_GPIO 0x09
- #define MCP_OLAT 0x0a
- //Deklaracja pinów
- #define CS_PIN GPIO_Pin_0
- #define CS_LINE GPIOC
- #define SCK_PIN GPIO_Pin_5
- #define SCK_LINE GPIOA
- #define MISO_PIN GPIO_Pin_6
- #define MISO_LINE GPIOA
- #define MOSI_PIN GPIO_Pin_7
- #define MOSI_LINE GPIOA
- void GPIOInit(void)
- {
- GPIO_InitTypeDef GPIOInit;
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOC, ENABLE);
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
- GPIO_StructInit(&GPIOInit);
- //piny SCK, MOSI
- GPIOInit.GPIO_Pin = SCK_PIN|MOSI_PIN; // SCK, MOSI
- GPIOInit.GPIO_Mode = GPIO_Mode_AF_PP;
- GPIOInit.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_Init(SCK_LINE, &GPIOInit);
- //Pin Miso
- GPIOInit.GPIO_Pin = MISO_PIN; // MISO
- GPIOInit.GPIO_Mode = GPIO_Mode_IN_FLOATING;
- GPIOInit.GPIO_Speed = GPIO_Speed_10MHz;
- GPIO_Init(MISO_LINE, &GPIOInit);
- //Pin CS
- GPIOInit.GPIO_Pin = CS_PIN;
- GPIOInit.GPIO_Mode = GPIO_Mode_Out_PP;
- GPIOInit.GPIO_Speed = GPIO_Speed_10MHz;
- GPIO_Init(CS_LINE, &GPIOInit);
- GPIO_SetBits(CS_LINE, CS_PIN);
- }
- void SPIInit(void)
- {
- SPI_InitTypeDef SPIInit;
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);
- SPI_StructInit(&SPIInit);
- SPIInit.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
- SPIInit.SPI_Mode = SPI_Mode_Master;
- SPIInit.SPI_CPOL = SPI_CPOL_Low;
- SPIInit.SPI_CPHA = SPI_CPHA_1Edge;
- SPIInit.SPI_NSS = SPI_NSS_Soft;
- SPIInit.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_16;
- SPI_Init(SPI1, &SPIInit);
- SPI_Cmd(SPI1, ENABLE);
- }
- uint8_t SPI_SEND(uint8_t byte)
- {
- while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
- SPI_I2S_SendData(SPI1, byte);
- while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);
- return SPI_I2S_ReceiveData(SPI1);
- }
- void MCP_WRITE(uint8_t rejestr, uint8_t wartosc)
- {
- GPIO_ResetBits(CS_LINE, CS_PIN);
- SPI_SEND(0x40);
- SPI_SEND(rejestr);
- SPI_SEND(wartosc);
- GPIO_SetBits(CS_LINE, CS_PIN);
- }
Dane najłatwiej przesyłać w postaci tablic zapalając i gasząc z odpowiednią częstotliwością. Poniżej dwie tablice dla dwóch diod. Pozwalają one na regulacje co 10%.
- uint8_t PWM10_Value_Table2[10] = { 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
- uint8_t PWM20_Value_Table2[10] = { 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
- uint8_t PWM30_Value_Table2[10] = { 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
- uint8_t PWM40_Value_Table2[10] = { 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
- uint8_t PWM50_Value_Table2[10] = { 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00 };
- uint8_t PWM60_Value_Table2[10] = { 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00 };
- uint8_t PWM70_Value_Table2[10] = { 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00 };
- uint8_t PWM80_Value_Table2[10] = { 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00 };
- uint8_t PWM90_Value_Table2[10] = { 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00 };
- uint8_t PWM10_Value_Table5[10] = { 0x1E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E };
- uint8_t PWM20_Value_Table5[10] = { 0x1E, 0x1E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E };
- uint8_t PWM30_Value_Table5[10] = { 0x1E, 0x1E, 0x1E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E };
- uint8_t PWM40_Value_Table5[10] = { 0x1E, 0x1E, 0x1E, 0x1E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E };
- uint8_t PWM50_Value_Table5[10] = { 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E };
- uint8_t PWM60_Value_Table5[10] = { 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x0E, 0x0E, 0x0E, 0x0E };
- uint8_t PWM70_Value_Table5[10] = { 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x0E, 0x0E, 0x0E };
- uint8_t PWM80_Value_Table5[10] = { 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x0E, 0x0E };
- uint8_t PWM90_Value_Table5[10] = { 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x0E };
Można także przygotować tablicę wielowymiarową z zawartymi wszystkimi potrzebnymi danymi. Na tych tablicach można dokonywać operacji poprzez operacje bitowe jak przesunięcia, negacja czy ustawianie.
Dane tablice wywołać można np. w pętli for, przechodząc po każdym z elementów.
74HC595
Drugi rejestr przesuwny jest włączany w podobny sposób, różnica jest jedynie w sposobie podłączenia oraz przesyłania danych:
Podłączenie jest następujące:
- DS - Data, SPI1 MOSI, PA5
- OE - PC0
- ST_CP - PC3
- SH_CP - SPI Clock; PA5
- MR - GND
- Q7 - NC
Dane do PWM wgrywane są na tej samej zasadzie:
- uint8_t PWM10_Value_Table2[10] = { 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
- uint8_t PWM20_Value_Table2[10] = { 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
- uint8_t PWM30_Value_Table2[10] = { 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
- uint8_t PWM40_Value_Table2[10] = { 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
- uint8_t PWM50_Value_Table2[10] = { 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00 };
- uint8_t PWM60_Value_Table2[10] = { 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00 };
- uint8_t PWM70_Value_Table2[10] = { 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00 };
- uint8_t PWM80_Value_Table2[10] = { 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00 };
- uint8_t PWM90_Value_Table2[10] = { 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00 };
- uint8_t PWM10_Value_Table5[10] = { 0x1E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E };
- uint8_t PWM20_Value_Table5[10] = { 0x1E, 0x1E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E };
- uint8_t PWM30_Value_Table5[10] = { 0x1E, 0x1E, 0x1E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E };
- uint8_t PWM40_Value_Table5[10] = { 0x1E, 0x1E, 0x1E, 0x1E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E };
- uint8_t PWM50_Value_Table5[10] = { 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E };
- uint8_t PWM60_Value_Table5[10] = { 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x0E, 0x0E, 0x0E, 0x0E };
- uint8_t PWM70_Value_Table5[10] = { 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x0E, 0x0E, 0x0E };
- uint8_t PWM80_Value_Table5[10] = { 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x0E, 0x0E };
- uint8_t PWM90_Value_Table5[10] = { 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x0E };
- //Deklaracja pinów
- #define CS_PIN GPIO_Pin_0
- #define CS_LINE GPIOC
- #define SCK_PIN GPIO_Pin_5
- #define SCK_LINE GPIOA
- #define MISO_PIN GPIO_Pin_6
- #define MISO_LINE GPIOA
- #define MOSI_PIN GPIO_Pin_7
- #define MOSI_LINE GPIOA
- #define ST_CP_PIN GPIO_Pin_3
- #define ST_CP_LINE GPIOC
- void GPIOInit(void)
- {
- GPIO_InitTypeDef GPIOInit;
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOC, ENABLE);
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
- GPIO_StructInit(&GPIOInit);
- //piny SCK, MOSI
- GPIOInit.GPIO_Pin = SCK_PIN|MOSI_PIN; // SCK, MOSI
- GPIOInit.GPIO_Mode = GPIO_Mode_AF_PP;
- GPIOInit.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_Init(SCK_LINE, &GPIOInit);
- //Pin Miso
- GPIOInit.GPIO_Pin = MISO_PIN; // MISO
- GPIOInit.GPIO_Mode = GPIO_Mode_IN_FLOATING;
- GPIOInit.GPIO_Speed = GPIO_Speed_10MHz;
- GPIO_Init(MISO_LINE, &GPIOInit);
- //Pin CS
- GPIOInit.GPIO_Pin = CS_PIN;
- GPIOInit.GPIO_Mode = GPIO_Mode_Out_PP;
- GPIOInit.GPIO_Speed = GPIO_Speed_10MHz;
- GPIO_Init(CS_LINE, &GPIOInit);
- GPIO_SetBits(CS_LINE, CS_PIN);
- GPIOInit.GPIO_Pin = ST_CP_PIN;
- GPIOInit.GPIO_Mode = GPIO_Mode_Out_PP;
- GPIOInit.GPIO_Speed = GPIO_Speed_10MHz;
- GPIO_Init(ST_CP_LINE, &GPIOInit);
- }
- void SPIInit(void)
- {
- SPI_InitTypeDef SPIInit;
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);
- SPI_StructInit(&SPIInit);
- SPIInit.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
- SPIInit.SPI_Mode = SPI_Mode_Master;
- SPIInit.SPI_CPOL = SPI_CPOL_Low;
- SPIInit.SPI_CPHA = SPI_CPHA_1Edge;
- SPIInit.SPI_DataSize = SPI_DataSize_8b;
- SPIInit.SPI_NSS = SPI_NSS_Soft | SPI_NSSInternalSoft_Set;;
- SPIInit.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_16;
- SPI_Init(SPI1, &SPIInit);
- SPI_Cmd(SPI1, ENABLE);
- }
- uint8_t SPI_SEND(uint8_t byte)
- {
- while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
- SPI_I2S_SendData(SPI1, byte);
- while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);
- return SPI_I2S_ReceiveData(SPI1);
- }
- void HC595_WRITE(uint8_t wartosc)
- {
- GPIO_ResetBits(ST_CP_LINE, ST_CP_PIN);
- GPIO_SetBits(CS_LINE, CS_PIN);
- SPI_SEND(wartosc);
- GPIO_SetBits(ST_CP_LINE, ST_CP_PIN);
- GPIO_ResetBits(CS_LINE, CS_PIN);
- }