├── 4 - I2C EEPROM with error handling
├── STM32_EEPROM.h
├── main.c
└── STM32_EEPROM.c
├── 8 - F4 Dot Matrix Controller
├── defines.h
├── MatrixController.c
└── initimage.c
├── 7 - L152 Disco PWM Generator
├── L1_LCD.h
├── L1_Disco.h
├── L1_Disco.c
├── main.c
└── L1_LCD.c
├── 6 - INA226
├── main.c
├── F7_INA226.h
└── F7_INA226.c
├── README.md
├── 1 - TC74 Temperature Measurement
└── main.c
├── 2 - TC74 with error handling
└── main.c
└── 3 - TC74 with low power
└── main.c
/4 - I2C EEPROM with error handling/STM32_EEPROM.h:
--------------------------------------------------------------------------------
1 | #ifndef __STM32_EEPROM_H
2 | #define __STM32_EEPROM_H
3 | #endif
4 |
5 | #define I2C_TIMEOUT_MAX 100000
6 |
7 | #include "stm32f4xx_i2c.h"
8 | #include "stm32f4xx_rcc.h"
9 | #include "stm32f4xx_gpio.h"
10 |
11 | void I2C_Memory_Init(void);
12 |
13 | int I2C_Memory_Read(I2C_TypeDef*, uint8_t);
14 |
15 | int I2C_Memory_Write(I2C_TypeDef*, uint8_t, uint8_t);
16 |
--------------------------------------------------------------------------------
/4 - I2C EEPROM with error handling/main.c:
--------------------------------------------------------------------------------
1 | /**
2 | ********************************************************************************
3 | * @brief I2C EEPROM library example
4 | * @date Nov 2015
5 | * @version 1.0
6 | * @author George Christidis
7 | ********************************************************************************
8 | * @details
9 | This program uses the I2C EEPROM library provided to read and write
10 | data to an EEPROM chip via I2C. It uses I2C3 (PA8 for SCL, PC9 for
11 | SDA) with a 24LC01B chip.
12 | ******************************************************************************
13 | */
14 |
15 | /* Includes ------------------------------------------------------------------*/
16 |
17 | #include "STM32_EEPROM.h"
18 |
19 |
20 | int main()
21 | {
22 | uint8_t data=0xAA;
23 |
24 | I2C_Memory_Init();
25 |
26 | I2C_Memory_Write(I2C3, 0x00, data);
27 |
28 | I2C_Memory_Read(I2C3, 0x00);
29 |
30 | while(1);
31 | }
32 |
--------------------------------------------------------------------------------
/8 - F4 Dot Matrix Controller/defines.h:
--------------------------------------------------------------------------------
1 | #ifndef DEFINES_H
2 | #define DEFINES_H
3 |
4 | #define COLDEPTH 3
5 | #define BRIGHTNESS 100
6 | #define ROWS 32
7 | #define COLUMNS 64
8 |
9 | #define R1PORT GPIOG
10 | #define R1PIN GPIO_Pin_9
11 | #define G1PORT GPIOD
12 | #define G1PIN GPIO_Pin_6
13 | #define B1PORT GPIOD
14 | #define B1PIN GPIO_Pin_7
15 | #define R2PORT GPIOD
16 | #define R2PIN GPIO_Pin_4
17 | #define G2PORT GPIOD
18 | #define G2PIN GPIO_Pin_5
19 | #define B2PORT GPIOD
20 | #define B2PIN GPIO_Pin_2
21 |
22 | #define ROW0PORT GPIOD
23 | #define ROW0PIN GPIO_Pin_3
24 | #define ROW1PORT GPIOD
25 | #define ROW1PIN GPIO_Pin_0
26 | #define ROW2PORT GPIOD
27 | #define ROW2PIN GPIO_Pin_1
28 | #define ROW3PORT GPIOC
29 | #define ROW3PIN GPIO_Pin_11
30 |
31 | #define CLKPORT GPIOC
32 | #define CLKPIN GPIO_Pin_12
33 | #define LEPORT GPIOA
34 | #define LEPIN GPIO_Pin_15
35 | #define OEPORT GPIOC
36 | #define OEPIN GPIO_Pin_10
37 |
38 | #endif
39 |
--------------------------------------------------------------------------------
/7 - L152 Disco PWM Generator/L1_LCD.h:
--------------------------------------------------------------------------------
1 | /**
2 | ********************************************************************************
3 | * @brief STM32 L152 Discovery LCD
4 | * @date Mar 2016
5 | * @version 1.0
6 | * @author George Christidis
7 | ********************************************************************************
8 | * @details
9 | This library provides basic functions to initialize the onboard LCD
10 | and display text and bargraphs.
11 | ******************************************************************************
12 | */
13 |
14 | #ifndef __LCD_H
15 | #define __LCD_H
16 |
17 | #include "stm32l1xx_gpio.h"
18 | #include "stm32l1xx_rcc.h"
19 | #include "stm32l1xx_tim.h"
20 | #include "stm32l_discovery_lcd.h"
21 | #include "stm32l1xx_syscfg.h"
22 |
23 | /* Macros used for set/reset bar LCD bar */
24 | #define BAR0_ON t_bar[1] |= 8
25 | #define BAR0_OFF t_bar[1] &= ~8
26 | #define BAR1_ON t_bar[0] |= 8
27 | #define BAR1_OFF t_bar[0] &= ~8
28 | #define BAR2_ON t_bar[1] |= 2
29 | #define BAR2_OFF t_bar[1] &= ~2
30 | #define BAR3_ON t_bar[0] |= 2
31 | #define BAR3_OFF t_bar[0] &= ~2
32 |
33 | void LCDInit(void);
34 |
35 | void LCD_GLASS_PreInit(void);
36 |
37 | void bargraph(int, int);
38 |
39 | void UpdateDisplay(char *, int, int, int);
40 |
41 | static unsigned char Slider_Position[7];
42 | extern uint8_t t_bar[2];
43 |
44 | #endif
45 |
--------------------------------------------------------------------------------
/7 - L152 Disco PWM Generator/L1_Disco.h:
--------------------------------------------------------------------------------
1 | /**
2 | ********************************************************************************
3 | * @brief STM32 L152 Discovery Library
4 | * @date Mar 2016
5 | * @version 1.0
6 | * @author George Christidis
7 | ********************************************************************************
8 | * @details
9 | This library contains the basic functions to initialize and switch
10 | on/off the onboard LEDs. It also initializes the user button and
11 | assigns it to the external interrupt EXTI0.
12 | ******************************************************************************
13 | */
14 |
15 | #idndef __L1_DISCO_H
16 | #define __L1_DISCO_H
17 | #include "stm32l1xx_gpio.h"
18 | #include "stm32l1xx_rcc.h"
19 |
20 | // GPIOs
21 | #define PIN_00 ((uint32_t)0)
22 | #define PIN_01 ((uint32_t)1)
23 | #define PIN_02 ((uint32_t)2)
24 | #define PIN_03 ((uint32_t)3)
25 | #define PIN_04 ((uint32_t)4)
26 | #define PIN_05 ((uint32_t)5)
27 | #define PIN_06 ((uint32_t)6)
28 | #define PIN_07 ((uint32_t)7)
29 | #define PIN_08 ((uint32_t)8)
30 | #define PIN_09 ((uint32_t)9)
31 | #define PIN_10 ((uint32_t)10)
32 | #define PIN_11 ((uint32_t)11)
33 | #define PIN_12 ((uint32_t)12)
34 | #define PIN_13 ((uint32_t)13)
35 | #define PIN_14 ((uint32_t)14)
36 | #define PIN_15 ((uint32_t)15)
37 | #define MODE_OUT ((uint32_t)1)
38 | #define MODE_AF ((uint32_t)2)
39 | #define MODE_ANA ((uint32_t)3)
40 | #define OTYPE_OD ((uint32_t)1)
41 | #define SPEED_50 ((uint32_t)2)
42 |
43 | #define LED_BLUE GPIO_Pin_6
44 | #define LED_GREEN GPIO_Pin_7
45 |
46 | #define DISCO_LedOn(led) GPIO_SetBits(GPIOB, led)
47 | #define DISCO_LedOff(led) GPIO_ResetBits(GPIOB, led)
48 | #define DISCO_LedToggle(led) GPIO_ToggleBits(GPIOB, led)
49 |
50 | void DISCO_LedInit(void);
51 | void DISCO_ButtonInit(void);
52 |
53 | #endif
54 |
--------------------------------------------------------------------------------
/7 - L152 Disco PWM Generator/L1_Disco.c:
--------------------------------------------------------------------------------
1 | /**
2 | ********************************************************************************
3 | * @brief STM32 L152 Discovery Library
4 | * @date Mar 2016
5 | * @version 1.0
6 | * @author George Christidis
7 | ********************************************************************************
8 | * @details
9 | This library contains the basic functions to initialize and switch
10 | on/off the onboard LEDs. It also initializes the user button and
11 | assigns it to the external interrupt EXTI0.
12 | ******************************************************************************
13 | */
14 |
15 | #include "MyL1_Disco.h"
16 |
17 | void DISCO_LedInit(void)
18 | {
19 | GPIO_InitTypeDef GPIO_InitStructure;
20 |
21 | RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);
22 | GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
23 | GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
24 | GPIO_InitStructure.GPIO_Pin = LED_GREEN | LED_BLUE;
25 | GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
26 | GPIO_InitStructure.GPIO_Speed = GPIO_Speed_400KHz;
27 | GPIO_Init(GPIOB, &GPIO_InitStructure);
28 | }
29 |
30 | void DISCO_ButtonInit(void)
31 | {
32 | GPIO_InitTypeDef GPIO_InitStruct;
33 | EXTI_InitTypeDef EXTI_InitStruct;
34 | NVIC_InitTypeDef NVIC_InitStruct;
35 |
36 | RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
37 | GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN;
38 | GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0;
39 | GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
40 | GPIO_InitStruct.GPIO_Speed = GPIO_Speed_400KHz;
41 | GPIO_Init(GPIOA, &GPIO_InitStruct);
42 |
43 | RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
44 | SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA, EXTI_PinSource0);
45 | EXTI_InitStruct.EXTI_Line = EXTI_Line0;
46 | EXTI_InitStruct.EXTI_LineCmd = ENABLE;
47 | EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt;
48 | EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Rising;
49 | EXTI_Init(&EXTI_InitStruct);
50 |
51 | NVIC_InitStruct.NVIC_IRQChannel = EXTI0_IRQn;
52 | NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
53 | NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 5;
54 | NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1;
55 | NVIC_Init(&NVIC_InitStruct);
56 |
57 | }
58 |
59 |
--------------------------------------------------------------------------------
/6 - INA226/main.c:
--------------------------------------------------------------------------------
1 | /**
2 | ********************************************************************************
3 | * @brief I2C INA226 library example
4 | * @date Feb 2016
5 | * @version 1.0
6 | * @author George Christidis
7 | ********************************************************************************
8 | * @details
9 | This program uses the I2C INA226 library provided to configure the
10 | monitor and read the bus voltag via I2C. It uses I2C1 (PB8 for SCL,
11 | PB9 for SDA).
12 | ******************************************************************************
13 | */
14 |
15 | #include "stm32fxxx_hal.h"
16 |
17 | #include "F7_INA226.h"
18 |
19 | void InitI2C1(void), InitGPIO(void);
20 | I2C_HandleTypeDef I2c1Handle;
21 |
22 | int main(){
23 | HAL_Init();
24 | InitI2C1();
25 | InitGPIO();
26 |
27 | INA226_setConfig(&I2c1Handle, INA226_ADDRESS, INA226_MODE_CONT_SHUNT_AND_BUS | INA226_VBUS_140uS | INA226_VBUS_140uS | INA226_AVG_1024);
28 |
29 | while(1) {
30 | if (INA226_getBusV(&I2c1Handle, INA226_ADDRESS) > 1000.0F) HAL_GPIO_WritePin(GPIOI, GPIO_PIN_1, GPIO_PIN_SET);
31 | else HAL_GPIO_WritePin(GPIOI, GPIO_PIN_1, GPIO_PIN_RESET);
32 | HAL_Delay (100);
33 | }
34 | }
35 |
36 | void InitGPIO(void) {
37 | GPIO_InitTypeDef GPIO_InitStruct;
38 |
39 | __HAL_RCC_GPIOI_CLK_ENABLE();
40 |
41 | GPIO_InitStruct.Pin = GPIO_PIN_1;
42 | GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
43 | GPIO_InitStruct.Pull = GPIO_NOPULL;
44 | GPIO_InitStruct.Speed = GPIO_SPEED_FAST;
45 | HAL_GPIO_Init(GPIOI, &GPIO_InitStruct);
46 | }
47 |
48 | void InitI2C1(void)
49 | {
50 | I2c1Handle.Instance = I2C1;
51 | I2c1Handle.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
52 | I2c1Handle.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
53 | I2c1Handle.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
54 | I2c1Handle.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
55 | I2c1Handle.Init.OwnAddress1 = 0x00;
56 | I2c1Handle.Init.Timing = 0x80200F73;
57 | if(HAL_I2C_Init(&I2c1Handle)!= HAL_OK)
58 |
59 | HAL_I2CEx_AnalogFilter_Config(&I2c1Handle, I2C_ANALOGFILTER_ENABLED);
60 | }
61 |
62 | void HAL_I2C_MspInit(I2C_HandleTypeDef* hi2c)
63 | {
64 | GPIO_InitTypeDef GPIO_InitStruct;
65 |
66 | if(hi2c->Instance==I2C1) {
67 | __HAL_RCC_I2C1_CLK_ENABLE();
68 | __HAL_RCC_GPIOB_CLK_ENABLE();
69 |
70 | GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9;
71 | GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
72 | GPIO_InitStruct.Pull = GPIO_NOPULL;
73 | GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
74 | GPIO_InitStruct.Alternate = GPIO_AF4_I2C1;
75 | HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # STM32-example-codes
2 | # Libraries and examples
3 | This project contains various example codes and custom libraries created for STM32 micronctrollers (L1, F4 and F7 variants).
4 | The L1 and F4 examples use the Standard Peripheral Library, whereas the F7 examples use the Hardware Abstraction Layer (HAL) drivers.
5 |
6 | 1. TC74 Temperature Measurement
7 | This program reads the temperature of a TC74 connected to an STM32L152
8 | discovery board. The sensor is connected on the I2C1 pins (SCL: PB6,
9 | SDA: PB7). It returns the value to a variable named temperature which then
10 | can be sent via UART, shown on a display or through a debug session.
11 |
12 | 2. TC74 with error handling
13 | This program reads the temperature of a TC74 connected to an STM32L152
14 | discovery board. The sensor is connected on the I2C1 pins (SCL: PB6,
15 | SDA: PB7). It returns the value to a variable named temperature which then
16 | can be sent via UART, shown on a display or through a debug session. In
17 | case of a timeout or an acknowledge failure, the program returns the error
18 | code and continues normal execution.
19 |
20 | 3. TC74 with low power
21 | This program reads the temperature of a TC74 connected to an STM32L152
22 | discovery board. The sensor is connected on the I2C1 pins (SCL: PB6,
23 | SDA: PB7). It returns the value to a variable named temperature which then
24 | can be sent via UART, shown on a display or through a debug session. The
25 | temperature is sampled every 5 seconds, via TIM6. After that the TC74
26 | enters standby mode until the next read.
27 |
28 | 4. I2C EEPROM with error handling
29 | Library and example in order to read and write data to an EEPROM chip
30 | via I2C. It uses I2C3 (PA8 for SCL, PC9 for SDA) with a 24LC01B chip.
31 |
32 | 5. SPI Potentiometer
33 | Library and example to operate a Microchip MCP41XXX potentiometer.
34 |
35 | 6. INA226
36 | Library and example for the I2C INA226 in order to configure the
37 | monitor and read the bus voltage via I2C. It uses I2C1 (PB8 for SCL,
38 | PB9 for SDA).
39 |
40 | 7. L152 Disco PWM Generator
41 | This program output a PWM signal to PB7, with variable frequency and
42 | duty cycle. The values are set using the Discovery's touch sensor and
43 | are displayed on the embedded LCD. The user button is pressed to
44 | change between setting the frequency and the duty cycle.
45 |
46 | 8. F4 Dot Matrix Controller
47 | This example shows how to drive an 64x32 Dot Matrix Display using
48 | an STM32F429 Discovery board. It uses UART to get new frames and stores
49 | them in two different memory banks.
50 |
--------------------------------------------------------------------------------
/1 - TC74 Temperature Measurement/main.c:
--------------------------------------------------------------------------------
1 | /**
2 | ******************************************************************************
3 | * @brief TC74 temperature sensor simple example code on STM32
4 | * @date Jan 2015
5 | * @version 1.0
6 | * @author George Christidis
7 | ******************************************************************************
8 | * @details
9 | This program reads the temperature of a TC74 connected to an STM32L152
10 | discovery board. The sensor is connected on the I2C1 pins (SCL: PB6,
11 | SDA: PB7). It returns the value to a variable named temperature which then
12 | can be sent via UART, shown on a display or through a debug session.
13 | ******************************************************************************
14 | */
15 |
16 | /* Includes ------------------------------------------------------------------*/
17 |
18 | #include "stm32l1xx_usart.h"
19 | #include "stm32l1xx_rcc.h"
20 | #include "stm32l1xx_gpio.h"
21 | #include "stm32l1xx_tim.h"
22 | #include "stm32l1xx_i2c.h"
23 |
24 | #define TC74_ADDRESS 0x9A // TC74 A5 address
25 | #define I2CTIMEOUT 50000
26 |
27 | void TC74_Config(void);
28 | int TC74_Read_Temperature(uint8_t);
29 | void I2C_start(I2C_TypeDef *, uint8_t, uint8_t), I2C_write(I2C_TypeDef *, uint8_t), I2C_stop(I2C_TypeDef *);
30 | int8_t I2C_read_ack(I2C_TypeDef *), I2C_read_nack(I2C_TypeDef *);
31 |
32 | int main()
33 | {
34 | int temperature;
35 |
36 | TC74_Config();
37 | temperature=TC74_Read_Temperature(TC74_ADDRESS);
38 |
39 | while(1);
40 | }
41 |
42 | void TC74_Config(void)
43 | {
44 | GPIO_InitTypeDef GPIO_InitStructure;
45 | I2C_InitTypeDef I2C_InitStructure;
46 |
47 | RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);
48 | RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
49 |
50 | GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_I2C1);
51 | GPIO_PinAFConfig(GPIOB, GPIO_PinSource7, GPIO_AF_I2C1);
52 | GPIO_StructInit(&GPIO_InitStructure);
53 | GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
54 | GPIO_InitStructure.GPIO_Speed = GPIO_Speed_40MHz;
55 | GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
56 | GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
57 | GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
58 | GPIO_Init(GPIOB, &GPIO_InitStructure);
59 |
60 | I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
61 | I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
62 | I2C_InitStructure.I2C_ClockSpeed = 10000;
63 | I2C_InitStructure.I2C_Mode = I2C_Mode_SMBusHost;
64 | I2C_InitStructure.I2C_OwnAddress1 = 0x00;
65 | I2C_Init(I2C1, &I2C_InitStructure);
66 | I2C_Cmd(I2C1, ENABLE);
67 | }
68 |
69 | int TC74_Read_Temperature(uint8_t TC74address)
70 | {
71 | int8_t data1, data2;
72 |
73 | I2C_start(I2C1, TC74address, I2C_Direction_Transmitter);
74 | I2C_write(I2C1,0x00);
75 | I2C_stop(I2C1);
76 | I2C_start(I2C1, TC74address, I2C_Direction_Receiver);
77 | data1 = I2C_read_ack(I2C1);
78 | data2 = I2C_read_nack(I2C1);
79 | return data1;
80 | }
81 |
82 | void I2C_start(I2C_TypeDef* I2Cx, uint8_t address, uint8_t direction)
83 | {
84 | while(I2C_GetFlagStatus(I2Cx, I2C_FLAG_BUSY));
85 | I2C_GenerateSTART(I2Cx, ENABLE);
86 | while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT)) ;
87 | I2C_Send7bitAddress(I2Cx, address, direction);
88 | if (direction== I2C_Direction_Transmitter) {
89 | while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
90 | }
91 | else if(direction == I2C_Direction_Receiver) {
92 | while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));
93 | }
94 | }
95 |
96 | void I2C_write(I2C_TypeDef* I2Cx, uint8_t data)
97 | {
98 | I2C_SendData(I2Cx, data);
99 | while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
100 | }
101 | void I2C_stop(I2C_TypeDef* I2Cx)
102 | {
103 | I2C_GenerateSTOP(I2Cx, ENABLE);
104 | }
105 |
106 | int8_t I2C_read_ack(I2C_TypeDef* I2Cx)
107 | {
108 | int8_t data;
109 |
110 | I2C_AcknowledgeConfig(I2Cx, ENABLE);
111 | while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_RECEIVED));
112 | data=I2C_ReceiveData(I2Cx);
113 |
114 | return data;
115 | }
116 |
117 | int8_t I2C_read_nack(I2C_TypeDef* I2Cx)
118 | {
119 | uint8_t data;
120 |
121 | I2C_AcknowledgeConfig(I2Cx, DISABLE);
122 | I2C_GenerateSTOP(I2Cx, ENABLE);
123 | while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_RECEIVED));
124 | data=I2C_ReceiveData(I2Cx);
125 |
126 | return data;
127 | }
128 |
--------------------------------------------------------------------------------
/7 - L152 Disco PWM Generator/main.c:
--------------------------------------------------------------------------------
1 | /**
2 | ********************************************************************************
3 | * @brief L152 Discovery PWM Generator
4 | * @date Mar 2016
5 | * @version 1.0
6 | * @author George Christidis
7 | ********************************************************************************
8 | * @details
9 | This program output a PWM signal to PB7, with variable frequency and
10 | duty cycle. The values are set using the Discovery's touch sensor and
11 | are displayed on the embedded LCD. The user button is pressed to
12 | change between setting the frequency and the duty cycle.
13 | ******************************************************************************
14 | */
15 |
16 | #include "L1_LCD.h"
17 | #include "L1_Disco.h"
18 | #include "TSL.h"
19 | #include "Delay.h"
20 | #include "stdio.h"
21 | #include "stm32l1xx_rcc.h"
22 | #include "stm32l1xx_gpio.h"
23 | #include "stm32l1xx_tim.h"
24 | #include "stm32l_discovery_lcd.h"
25 | #include "stm32l1xx_syscfg.h"
26 |
27 | enum selection {FREQ=0, DUTY} state;
28 | char displaystring[7];
29 | volatile double frequency=50., duty=50.;
30 | volatile int touchvalue;
31 | void UpdateDisplay1(void), UpdatePWM(double, double), TIM4Init();
32 |
33 | void EXTI0_IRQHandler(void)
34 | {
35 | if (EXTI_GetITStatus(EXTI_Line0) != RESET) {
36 | DISCO_LedToggle(LED_BLUE);
37 | if (state==FREQ) state=DUTY;
38 | else state=FREQ;
39 | touchvalue=getTouch();
40 | EXTI_ClearITPendingBit(EXTI_Line0);
41 | }
42 | }
43 |
44 | int main()
45 | {
46 | LCDInit();
47 | DISCO_LedInit();
48 | DISCO_ButtonInit();
49 | DelayInit();
50 | TIM4Init();
51 | TSLInit();
52 |
53 | LCD_GLASS_DisplayString((uint8_t*)" FREQ");
54 | Delayms(2000);
55 | LCD_GLASS_Clear();
56 | DISCO_LedOn(LED_BLUE);
57 |
58 |
59 | while(1)
60 | {
61 | if (TSL_user_Action() == TSL_STATUS_OK) {
62 | if (state==FREQ) {
63 | if (getTouch()!=touchvalue){
64 | frequency = 200.*getTouch()/127.;
65 | if (frequency<0.1) frequency=0.1;
66 | }
67 | }
68 | if (state==DUTY) {
69 | if (getTouch()!=touchvalue){
70 | duty = 100.*getTouch()/127.;
71 | if (duty<0.5) duty=0.5;
72 | }
73 | }
74 | UpdatePWM(frequency*1000., duty);
75 | UpdateDisplay1();
76 | }
77 | }
78 | }
79 |
80 | void UpdateDisplay1(void)
81 | {
82 | bargraph((int) duty, 100);
83 | if (state==FREQ) sprintf(displaystring,"f%4.2dk", (int) (10*frequency));
84 | if (state==DUTY) sprintf(displaystring,"d%4.2d%%", (int) (10*duty));
85 | LCD_GLASS_WriteChar((unsigned char *)displaystring + 0, 0, COLUMN_ON, 1);
86 | LCD_GLASS_WriteChar((unsigned char *)displaystring + 1, 0, 0, 2);
87 | LCD_GLASS_WriteChar((unsigned char *)displaystring + 2, 0, 0, 3);
88 | LCD_GLASS_WriteChar((unsigned char *)displaystring + 3, POINT_ON, 0, 4);
89 | LCD_GLASS_WriteChar((unsigned char *)displaystring + 4, 0, 0, 5);
90 | LCD_GLASS_WriteChar((unsigned char *)displaystring + 5, 0, 0, 6);
91 | }
92 |
93 | void TIM4Init()
94 | {
95 | TIM_TimeBaseInitTypeDef TIM_InitStruct;
96 | TIM_OCInitTypeDef TIM_OCInitStruct;
97 | GPIO_InitTypeDef GPIO_InitStructure;
98 |
99 | RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4,ENABLE);
100 | TIM_InitStruct.TIM_ClockDivision = TIM_CKD_DIV1 ;
101 | TIM_InitStruct.TIM_CounterMode = TIM_CounterMode_Up;
102 | TIM_InitStruct.TIM_Period = 32000;
103 | TIM_InitStruct.TIM_Prescaler = 1;
104 | TIM_TimeBaseInit(TIM4, &TIM_InitStruct);
105 | TIM_Cmd(TIM4, ENABLE);
106 |
107 | TIM_OCInitStruct.TIM_OCMode = TIM_OCMode_PWM1;
108 | TIM_OCInitStruct.TIM_Pulse = 100;
109 | TIM_OCInitStruct.TIM_OutputState = TIM_OutputState_Enable;
110 | TIM_OCInitStruct.TIM_OCPolarity = TIM_OCPolarity_High;
111 | TIM_OC2Init(TIM4, &TIM_OCInitStruct);
112 |
113 | RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);
114 | GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
115 | GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
116 | GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
117 | GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
118 | GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
119 | GPIO_Init(GPIOB, &GPIO_InitStructure);
120 |
121 | TIM_OC2PreloadConfig(TIM4, TIM_OCPreload_Enable);
122 | GPIO_PinAFConfig(GPIOB, GPIO_PinSource7, GPIO_AF_TIM4);
123 |
124 | UpdatePWM(frequency, duty);
125 | }
126 |
127 | void UpdatePWM(double frequency, double duty)
128 | {
129 | //frequency in Hz, duty 0-100.0
130 | long int ratio;
131 |
132 | ratio = (long)SystemCoreClock/frequency;
133 | TIM4->PSC = (int)(ratio/0xFFFF);
134 |
135 | ratio = ((long)SystemCoreClock/(TIM4->PSC+1));
136 | TIM4->ARR = (int)(ratio/frequency)-1;
137 |
138 | TIM4->CCR2 = (int)((TIM4->ARR+1)*duty)/100-1;
139 | }
140 |
--------------------------------------------------------------------------------
/4 - I2C EEPROM with error handling/STM32_EEPROM.c:
--------------------------------------------------------------------------------
1 | /**
2 | ********************************************************************************
3 | * @brief STM32 Library for I2C EEPROM memory
4 | * @date Nov 2015
5 | * @version 1.0
6 | * @author George Christidis
7 | ********************************************************************************
8 | * @details
9 | This library contains the necessary functions to initialize, read and
10 | write data to an EEPROM using the I2C protocol. As an example, the
11 | code was used on an STM32F429 using the I2C3 peripheral (PA8 for SCL,
12 | PC9 for SDA) with a 24LC01B chip.
13 | ******************************************************************************
14 | */
15 |
16 | #include "STM32_EEPROM.h"
17 |
18 | void I2C_Memory_Init(void)
19 | {
20 | GPIO_InitTypeDef GPIO_InitStruct;
21 | I2C_InitTypeDef I2C_InitStruct;
22 |
23 | RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C3, ENABLE);
24 | RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
25 | RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);
26 |
27 | GPIO_InitStruct.GPIO_Pin = GPIO_Pin_8;
28 | GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
29 | GPIO_InitStruct.GPIO_OType = GPIO_OType_OD;
30 | GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;
31 | GPIO_InitStruct.GPIO_Speed = GPIO_Speed_2MHz;
32 | GPIO_Init(GPIOA, &GPIO_InitStruct);
33 |
34 | GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9;
35 | GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
36 | GPIO_InitStruct.GPIO_OType = GPIO_OType_OD;
37 | GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;
38 | GPIO_InitStruct.GPIO_Speed = GPIO_Speed_2MHz;
39 | GPIO_Init(GPIOC, &GPIO_InitStruct);
40 |
41 | GPIO_PinAFConfig(GPIOA, GPIO_PinSource8, GPIO_AF_I2C3); //SCL
42 | GPIO_PinAFConfig(GPIOC, GPIO_PinSource9, GPIO_AF_I2C3); //SDA
43 |
44 | I2C_InitStruct.I2C_Mode = I2C_Mode_I2C;
45 | I2C_InitStruct.I2C_DutyCycle = I2C_DutyCycle_2;
46 | I2C_InitStruct.I2C_OwnAddress1 = 0x00;
47 | I2C_InitStruct.I2C_Ack = I2C_Ack_Disable;
48 | I2C_InitStruct.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
49 | I2C_InitStruct.I2C_ClockSpeed = 100000;
50 | I2C_DeInit(I2C3);
51 | I2C_Init(I2C3, &I2C_InitStruct);
52 | I2C_Cmd(I2C3, ENABLE);
53 | }
54 |
55 | int I2C_Memory_Read(I2C_TypeDef* I2Cx, uint8_t address)
56 | {
57 | uint32_t timeout = I2C_TIMEOUT_MAX;
58 | uint8_t Data = 0;
59 |
60 | I2C_GenerateSTART(I2Cx, ENABLE);
61 |
62 | timeout = I2C_TIMEOUT_MAX;
63 | while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT))
64 | {
65 | if ((timeout--) == 0) return -1;
66 | }
67 | I2C_Send7bitAddress(I2Cx, 0xA0, I2C_Direction_Transmitter);
68 |
69 | timeout = I2C_TIMEOUT_MAX;
70 | while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))
71 | {
72 | if ((timeout--) == 0) return -1;
73 | }
74 |
75 | I2C_SendData(I2Cx, address);
76 |
77 | timeout = I2C_TIMEOUT_MAX;
78 | while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED))
79 | {
80 | if ((timeout--) == 0) return -1;
81 | }
82 |
83 | I2C_GenerateSTART(I2Cx, ENABLE);
84 | timeout = I2C_TIMEOUT_MAX;
85 | while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT))
86 | {
87 | if ((timeout--) == 0) return -1;
88 | }
89 | I2C_Send7bitAddress(I2Cx, 0xA0, I2C_Direction_Receiver);
90 |
91 | timeout = I2C_TIMEOUT_MAX;
92 | while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED))
93 | {
94 | if ((timeout--) == 0) return -1;
95 | }
96 |
97 | I2C_AcknowledgeConfig(I2Cx, DISABLE);
98 |
99 | timeout = I2C_TIMEOUT_MAX;
100 | while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_RECEIVED))
101 | {
102 | if ((timeout--) == 0) return -1;
103 | }
104 |
105 | I2C_GenerateSTOP(I2Cx, ENABLE);
106 | Data = I2C_ReceiveData(I2Cx);
107 |
108 | return Data;
109 | }
110 |
111 | int I2C_Memory_Write(I2C_TypeDef* I2Cx, uint8_t address, uint8_t data)
112 | {
113 | uint32_t timeout = I2C_TIMEOUT_MAX;
114 |
115 | I2C_GenerateSTART(I2Cx, ENABLE);
116 |
117 | timeout = I2C_TIMEOUT_MAX;
118 | while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT))
119 | {
120 | if ((timeout--) == 0) return -1;
121 | }
122 | I2C_Send7bitAddress(I2Cx, 0xA0, I2C_Direction_Transmitter);
123 |
124 | timeout = I2C_TIMEOUT_MAX;
125 | while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))
126 | {
127 | if ((timeout--) == 0) return -1;
128 | }
129 |
130 | I2C_SendData(I2Cx, address);
131 |
132 | timeout = I2C_TIMEOUT_MAX;
133 | while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED))
134 | {
135 | if ((timeout--) == 0) return -1;
136 | }
137 |
138 | I2C_SendData(I2Cx, data);
139 |
140 | timeout = I2C_TIMEOUT_MAX;
141 | while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED))
142 | {
143 | if ((timeout--) == 0) return -1;
144 | }
145 | I2C_GenerateSTOP(I2Cx, ENABLE);
146 |
147 | return 0;
148 | }
149 |
--------------------------------------------------------------------------------
/7 - L152 Disco PWM Generator/L1_LCD.c:
--------------------------------------------------------------------------------
1 | /**
2 | ********************************************************************************
3 | * @brief STM32 L152 Discovery LCD
4 | * @date Mar 2016
5 | * @version 1.0
6 | * @author George Christidis
7 | ********************************************************************************
8 | * @details
9 | This library provides basic functions to initialize the onboard LCD
10 | and display text and bargraphs.
11 | ******************************************************************************
12 | */
13 |
14 | #include "MyL1_LCD.h"
15 |
16 | void LCDInit(void)
17 | {
18 | LCD_GLASS_PreInit();
19 | LCD_GLASS_Init();
20 | }
21 |
22 | void LCD_GLASS_PreInit(void)
23 | {
24 | GPIO_InitTypeDef GPIO_InitStructure;
25 |
26 | RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA | RCC_AHBPeriph_GPIOB | RCC_AHBPeriph_GPIOC, ENABLE);
27 |
28 | RCC_APB1PeriphClockCmd(RCC_APB1Periph_LCD | RCC_APB1Periph_PWR, ENABLE);
29 |
30 | PWR_RTCAccessCmd(ENABLE);
31 |
32 | RCC_RTCResetCmd(ENABLE);
33 | RCC_RTCResetCmd(DISABLE);
34 |
35 | RCC_LSEConfig(RCC_LSE_ON);
36 |
37 | while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET)
38 | {}
39 |
40 | RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);
41 |
42 | GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
43 | GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
44 | GPIO_InitStructure.GPIO_Speed = GPIO_Speed_40MHz;
45 |
46 | GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_15;
47 | GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
48 | GPIO_Init(GPIOA, &GPIO_InitStructure);
49 |
50 | GPIO_PinAFConfig(GPIOA, GPIO_PinSource1, GPIO_AF_LCD) ;
51 | GPIO_PinAFConfig(GPIOA, GPIO_PinSource2, GPIO_AF_LCD) ;
52 | GPIO_PinAFConfig(GPIOA, GPIO_PinSource3, GPIO_AF_LCD) ;
53 | GPIO_PinAFConfig(GPIOA, GPIO_PinSource8, GPIO_AF_LCD) ;
54 | GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_LCD) ;
55 | GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_LCD) ;
56 | GPIO_PinAFConfig(GPIOA, GPIO_PinSource15, GPIO_AF_LCD) ;
57 |
58 | GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_8 | GPIO_Pin_9 \
59 | | GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
60 | GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
61 | GPIO_Init(GPIOB, &GPIO_InitStructure);
62 |
63 | GPIO_PinAFConfig(GPIOB, GPIO_PinSource3, GPIO_AF_LCD) ;
64 | GPIO_PinAFConfig(GPIOB, GPIO_PinSource4, GPIO_AF_LCD) ;
65 | GPIO_PinAFConfig(GPIOB, GPIO_PinSource5, GPIO_AF_LCD) ;
66 | GPIO_PinAFConfig(GPIOB, GPIO_PinSource8, GPIO_AF_LCD) ;
67 | GPIO_PinAFConfig(GPIOB, GPIO_PinSource9, GPIO_AF_LCD) ;
68 | GPIO_PinAFConfig(GPIOB, GPIO_PinSource10, GPIO_AF_LCD) ;
69 | GPIO_PinAFConfig(GPIOB, GPIO_PinSource11, GPIO_AF_LCD) ;
70 | GPIO_PinAFConfig(GPIOB, GPIO_PinSource12, GPIO_AF_LCD) ;
71 | GPIO_PinAFConfig(GPIOB, GPIO_PinSource13, GPIO_AF_LCD) ;
72 | GPIO_PinAFConfig(GPIOB, GPIO_PinSource14, GPIO_AF_LCD) ;
73 | GPIO_PinAFConfig(GPIOB, GPIO_PinSource15, GPIO_AF_LCD) ;
74 |
75 | GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_6 \
76 | | GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11 ;
77 | GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
78 | GPIO_Init(GPIOC, &GPIO_InitStructure);
79 |
80 |
81 | GPIO_PinAFConfig(GPIOC, GPIO_PinSource0, GPIO_AF_LCD) ;
82 | GPIO_PinAFConfig(GPIOC, GPIO_PinSource1, GPIO_AF_LCD) ;
83 | GPIO_PinAFConfig(GPIOC, GPIO_PinSource2, GPIO_AF_LCD) ;
84 | GPIO_PinAFConfig(GPIOC, GPIO_PinSource3, GPIO_AF_LCD) ;
85 | GPIO_PinAFConfig(GPIOC, GPIO_PinSource6, GPIO_AF_LCD) ;
86 | GPIO_PinAFConfig(GPIOC, GPIO_PinSource7, GPIO_AF_LCD) ;
87 | GPIO_PinAFConfig(GPIOC, GPIO_PinSource8, GPIO_AF_LCD) ;
88 | GPIO_PinAFConfig(GPIOC, GPIO_PinSource9, GPIO_AF_LCD) ;
89 | GPIO_PinAFConfig(GPIOC, GPIO_PinSource10, GPIO_AF_LCD) ;
90 | GPIO_PinAFConfig(GPIOC, GPIO_PinSource11, GPIO_AF_LCD) ;
91 | }
92 |
93 | void bargraph(int value, int max)
94 | {
95 | double percentage=(double)value/(double)max;
96 | BAR0_OFF;
97 | BAR1_OFF;
98 | BAR2_OFF;
99 | BAR3_OFF;
100 | if (percentage>0.25) BAR0_ON;
101 | if (percentage>=0.5) BAR1_ON;
102 | if (percentage>=0.75) BAR2_ON;
103 | if (percentage==1) BAR3_ON;
104 | LCD_bar();
105 | }
106 |
107 | void UpdateDisplay(char * displaystring, int columns, int points, int bars)
108 | {
109 | //displaystring: 6characters + terminator
110 | //points, columns: hexadecimal 0x111111: all on
111 | //bars: hexadecimal 0x1111: all on
112 | int i, point, column;
113 |
114 | if ((bars&0x0001)>0) BAR0_ON; else BAR0_OFF;
115 | if ((bars&0x0010)>0) BAR1_ON; else BAR1_OFF;
116 | if ((bars&0x0100)>0) BAR2_ON; else BAR2_OFF;
117 | if ((bars&0x1000)>0) BAR3_ON; else BAR3_OFF;
118 |
119 | for (i=0; i<6; i++){
120 | if ((points & (1<<(4*(5-i)))) > 0) point = POINT_ON;
121 | else point = 0;
122 | if ((columns & (1<<(4*(5-i))))> 0) column = COLUMN_ON;
123 | else column = 0;
124 | LCD_GLASS_WriteChar((unsigned char *)displaystring + i, point, column, i+1);
125 | }
126 | }
127 |
--------------------------------------------------------------------------------
/6 - INA226/F7_INA226.h:
--------------------------------------------------------------------------------
1 | /**
2 | ********************************************************************************
3 | * @brief STM32 HAL Library for INA226 Current/Power Monitor
4 | * @date Feb 2016
5 | * @version 1.0
6 | * @author George Christidis
7 | ********************************************************************************
8 | * @details
9 | This library contains the necessary functions to initialize, read and
10 | write data to the TI INA226 Current/Power Monitor using the I2C
11 | protocol.
12 | ******************************************************************************
13 | */
14 |
15 | #ifndef F7_INA226_H
16 | #define F7_INA226_H
17 |
18 | #include "stm32fxxx_hal.h"
19 | #include "stm32f7xx_hal_i2c.h"
20 | #include "arm_math.h"
21 |
22 | #ifndef INA226_ADDRESS
23 | #define INA226_ADDRESS 0x80
24 | #endif
25 |
26 | #define INA226_CALIB_VAL 1024
27 | #define INA226_CURRENTLSB 0.5F // mA/bit
28 | #define INA226_CURRENTLSB_INV 1/INA226_CURRENTLSB // bit/mA
29 | #define INA226_POWERLSB_INV 1/(INA226_CURRENTLSB*25) // bit/mW
30 | #define INA226_I2CTIMEOUT 10
31 |
32 | #define INA226_CONFIG 0x00 // Configuration Register (R/W)
33 | #define INA226_SHUNTV 0x01 // Shunt Voltage (R)
34 | #define INA226_BUSV 0x02 // Bus Voltage (R)
35 | #define INA226_POWER 0x03 // Power (R)
36 | #define INA226_CURRENT 0x04 // Current (R)
37 | #define INA226_CALIB 0x05 // Calibration (R/W)
38 | #define INA226_MASK 0x06 // Mask/Enable (R/W)
39 | #define INA226_ALERTL 0x07 // Alert Limit (R/W)
40 | #define INA226_MANUF_ID 0xFE // Manufacturer ID (R)
41 | #define INA226_DIE_ID 0xFF // Die ID (R)
42 |
43 | #define INA226_MODE_POWER_DOWN (0<<0) // Power-Down
44 | #define INA226_MODE_TRIG_SHUNT_VOLTAGE (1<<0) // Shunt Voltage, Triggered
45 | #define INA226_MODE_TRIG_BUS_VOLTAGE (2<<0) // Bus Voltage, Triggered
46 | #define INA226_MODE_TRIG_SHUNT_AND_BUS (3<<0) // Shunt and Bus, Triggered
47 | #define INA226_MODE_POWER_DOWN2 (4<<0) // Power-Down
48 | #define INA226_MODE_CONT_SHUNT_VOLTAGE (5<<0) // Shunt Voltage, Continuous
49 | #define INA226_MODE_CONT_BUS_VOLTAGE (6<<0) // Bus Voltage, Continuous
50 | #define INA226_MODE_CONT_SHUNT_AND_BUS (7<<0) // Shunt and Bus, Continuous
51 |
52 | // Shunt Voltage Conversion Time
53 | #define INA226_VSH_140uS (0<<3)
54 | #define INA226_VSH_204uS (1<<3)
55 | #define INA226_VSH_332uS (2<<3)
56 | #define INA226_VSH_588uS (3<<3)
57 | #define INA226_VSH_1100uS (4<<3)
58 | #define INA226_VSH_2116uS (5<<3)
59 | #define INA226_VSH_4156uS (6<<3)
60 | #define INA226_VSH_8244uS (7<<3)
61 |
62 | // Bus Voltage Conversion Time (VBUS CT Bit Settings[6-8])
63 | #define INA226_VBUS_140uS (0<<6)
64 | #define INA226_VBUS_204uS (1<<6)
65 | #define INA226_VBUS_332uS (2<<6)
66 | #define INA226_VBUS_588uS (3<<6)
67 | #define INA226_VBUS_1100uS (4<<6)
68 | #define INA226_VBUS_2116uS (5<<6)
69 | #define INA226_VBUS_4156uS (6<<6)
70 | #define INA226_VBUS_8244uS (7<<6)
71 |
72 | // Averaging Mode (AVG Bit Settings[9-11])
73 | #define INA226_AVG_1 (0<<9)
74 | #define INA226_AVG_4 (1<<9)
75 | #define INA226_AVG_16 (2<<9)
76 | #define INA226_AVG_64 (3<<9)
77 | #define INA226_AVG_128 (4<<9)
78 | #define INA226_AVG_256 (5<<9)
79 | #define INA226_AVG_512 (6<<9)
80 | #define INA226_AVG_1024 (7<<9)
81 |
82 | // Reset Bit (RST bit [15])
83 | #define INA226_RESET_ACTIVE (1<<15)
84 | #define INA226_RESET_INACTIVE (0<<15)
85 |
86 | // Mask/Enable Register
87 | #define INA226_MER_SOL (1<<15) // Shunt Voltage Over-Voltage
88 | #define INA226_MER_SUL (1<<14) // Shunt Voltage Under-Voltage
89 | #define INA226_MER_BOL (1<<13) // Bus Voltagee Over-Voltage
90 | #define INA226_MER_BUL (1<<12) // Bus Voltage Under-Voltage
91 | #define INA226_MER_POL (1<<11) // Power Over-Limit
92 | #define INA226_MER_CNVR (1<<10) // Conversion Ready
93 | #define INA226_MER_AFF (1<<4) // Alert Function Flag
94 | #define INA226_MER_CVRF (1<<3) // Conversion Ready Flag
95 | #define INA226_MER_OVF (1<<2) // Math Overflow Flag
96 | #define INA226_MER_APOL (1<<1) // Alert Polarity Bit
97 | #define INA226_MER_LEN (1<<0) // Alert Latch Enable
98 |
99 | #define INA226_MANUF_ID_DEFAULT 0x5449
100 | #define INA226_DIE_ID_DEFAULT 0x2260
101 |
102 | float32_t INA226_getBusV(I2C_HandleTypeDef *I2CHandler, uint16_t DevAddress);
103 | float32_t INA226_getCurrent(I2C_HandleTypeDef *I2CHandler, uint16_t DevAddress);
104 | float32_t INA226_getPower(I2C_HandleTypeDef *I2CHandler, uint16_t DevAddress);
105 |
106 | uint8_t INA226_setConfig(I2C_HandleTypeDef *I2CHandler, uint16_t DevAddress, uint16_t ConfigWord);
107 | uint16_t INA226_getConfig(I2C_HandleTypeDef *I2CHandler, uint16_t DevAddress);
108 | uint16_t INA226_getShuntV(I2C_HandleTypeDef *I2CHandler, uint16_t DevAddress);
109 | uint16_t INA226_getBusVReg(I2C_HandleTypeDef *I2CHandler, uint16_t DevAddress);
110 | uint16_t INA226_getPowerReg(I2C_HandleTypeDef *I2CHandler, uint16_t DevAddress);
111 | uint8_t INA226_setCalibrationReg(I2C_HandleTypeDef *I2CHandler, uint16_t DevAddress, uint16_t ConfigWord);
112 | uint16_t INA226_getCalibrationReg(I2C_HandleTypeDef *I2CHandler, uint16_t DevAddress);
113 | uint16_t INA226_getCurrentReg(I2C_HandleTypeDef *I2CHandler, uint16_t DevAddress);
114 | uint16_t INA226_getManufID(I2C_HandleTypeDef *I2CHandler, uint16_t DevAddress);
115 | uint16_t INA226_getDieID(I2C_HandleTypeDef *I2CHandler, uint16_t DevAddress);
116 | uint8_t INA226_setMaskEnable(I2C_HandleTypeDef *I2CHandler, uint16_t DevAddress, uint16_t ConfigWord);
117 | uint16_t INA226_getMaskEnable(I2C_HandleTypeDef *I2CHandler, uint16_t DevAddress);
118 | uint8_t INA226_setAlertLimit(I2C_HandleTypeDef *I2CHandler, uint16_t DevAddress, uint16_t ConfigWord);
119 | uint16_t INA226_getAlertLimit(I2C_HandleTypeDef *I2CHandler, uint16_t DevAddress);
120 |
121 | #endif
122 |
--------------------------------------------------------------------------------
/2 - TC74 with error handling/main.c:
--------------------------------------------------------------------------------
1 | /**
2 | ******************************************************************************
3 | * @brief TC74 temperature sensor example code on STM32 with error handling
4 | * @date Feb 2015
5 | * @version 1.0
6 | * @author George Christidis
7 | ******************************************************************************
8 | * @details
9 | This program reads the temperature of a TC74 connected to an STM32L152
10 | discovery board. The sensor is connected on the I2C1 pins (SCL: PB6,
11 | SDA: PB7). It returns the value to a variable named temperature which then
12 | can be sent via UART, shown on a display or through a debug session. In
13 | case of a timeout or an acknowledge failure, the program returns the error
14 | code and continues normal execution.
15 | ******************************************************************************
16 | */
17 |
18 | /* Includes ------------------------------------------------------------------*/
19 |
20 | #include "stm32l1xx_usart.h"
21 | #include "stm32l1xx_rcc.h"
22 | #include "stm32l1xx_gpio.h"
23 | #include "stm32l1xx_tim.h"
24 | #include "stm32l1xx_i2c.h"
25 |
26 | #define TC74_ADDRESS 0x9A // TC74 A5 address
27 | #define I2CTIMEOUT 50000
28 |
29 | void TC74_Config(void);
30 | int TC74_Read_Temperature(uint8_t);
31 | int I2C_start(I2C_TypeDef *, uint8_t, uint8_t), I2C_write(I2C_TypeDef *, uint8_t), I2C_stop(I2C_TypeDef *);
32 | int8_t I2C_read_ack(I2C_TypeDef *), I2C_read_nack(I2C_TypeDef *);
33 |
34 | int main()
35 | {
36 | int temperature;
37 |
38 | TC74_Config();
39 | temperature=TC74_Read_Temperature(TC74_ADDRESS);
40 |
41 | while(1);
42 | }
43 |
44 | void TC74_Config(void)
45 | {
46 | GPIO_InitTypeDef GPIO_InitStructure;
47 | I2C_InitTypeDef I2C_InitStructure;
48 |
49 | RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);
50 | RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
51 |
52 | GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_I2C1);
53 | GPIO_PinAFConfig(GPIOB, GPIO_PinSource7, GPIO_AF_I2C1);
54 | GPIO_StructInit(&GPIO_InitStructure);
55 | GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
56 | GPIO_InitStructure.GPIO_Speed = GPIO_Speed_40MHz;
57 | GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
58 | GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
59 | GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
60 | GPIO_Init(GPIOB, &GPIO_InitStructure);
61 |
62 | I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
63 | I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
64 | I2C_InitStructure.I2C_ClockSpeed = 10000;
65 | I2C_InitStructure.I2C_Mode = I2C_Mode_SMBusHost;
66 | I2C_InitStructure.I2C_OwnAddress1 = 0x00;
67 | I2C_Init(I2C1, &I2C_InitStructure);
68 | I2C_Cmd(I2C1, ENABLE);
69 | }
70 |
71 | int TC74_Read_Temperature(uint8_t TC74address)
72 | {
73 | int8_t data1, data2;
74 |
75 | if(I2C_start(I2C1, TC74address, I2C_Direction_Transmitter)>0) {
76 | return -127;
77 | }
78 | if(I2C_write(I2C1, 0x00)>0) return -127;
79 | if(I2C_stop(I2C1)==1) return -127;
80 |
81 | if(I2C_start(I2C1, TC74address, I2C_Direction_Receiver)>0) {
82 | return -127;
83 | }
84 | data1 = I2C_read_ack(I2C1);
85 | data2 = I2C_read_nack(I2C1);
86 |
87 | return data1;
88 | }
89 |
90 | int I2C_start(I2C_TypeDef* I2Cx, uint8_t address, uint8_t direction)
91 | {
92 | int i2c_timeout=I2CTIMEOUT;
93 | while(I2C_GetFlagStatus(I2Cx, I2C_FLAG_BUSY));
94 |
95 | I2C_GenerateSTART(I2Cx, ENABLE);
96 |
97 | while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT)){
98 | if(I2C_GetFlagStatus(I2Cx, I2C_FLAG_TIMEOUT)!=RESET) {
99 | I2C_ClearFlag(I2Cx, I2C_FLAG_TIMEOUT);
100 | return 1;
101 | }
102 | if(I2C_GetFlagStatus(I2Cx, I2C_FLAG_AF)!=RESET) {
103 | I2C_ClearFlag(I2Cx, I2C_FLAG_AF);
104 | return 2;
105 | }
106 | }
107 |
108 | I2C_Send7bitAddress(I2Cx, address, direction);
109 |
110 | if (direction== I2C_Direction_Transmitter) {
111 | while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)){
112 | if (I2C_GetFlagStatus(I2Cx, I2C_FLAG_TIMEOUT)!=RESET) {
113 | I2C_ClearFlag(I2Cx, I2C_FLAG_TIMEOUT);
114 | return 1;
115 | }
116 | if(I2C_GetFlagStatus(I2Cx, I2C_FLAG_AF)!=RESET) {
117 | I2C_ClearFlag(I2Cx, I2C_FLAG_AF);
118 | return 2;
119 | }
120 | }
121 | }
122 |
123 | else if(direction == I2C_Direction_Receiver) {
124 | while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)){
125 | if (I2C_GetFlagStatus(I2Cx, I2C_FLAG_TIMEOUT)!=RESET) {
126 | I2C_ClearFlag(I2Cx, I2C_FLAG_TIMEOUT);
127 | return 3;
128 | }
129 | if(I2C_GetFlagStatus(I2Cx, I2C_FLAG_AF)!=RESET) {
130 | I2C_ClearFlag(I2Cx, I2C_FLAG_AF);
131 | return 4;
132 | }
133 | }
134 | }
135 | return 0;
136 | }
137 |
138 | int I2C_write(I2C_TypeDef* I2Cx, uint8_t data)
139 | {
140 | I2C_SendData(I2Cx, data);
141 |
142 | while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED)){
143 | if (I2C_GetFlagStatus(I2Cx, I2C_FLAG_TIMEOUT)!=RESET) {
144 | I2C_ClearFlag(I2Cx, I2C_FLAG_TIMEOUT);
145 | return 1;
146 | }
147 | if(I2C_GetFlagStatus(I2Cx, I2C_FLAG_AF)!=RESET) {
148 | I2C_ClearFlag(I2Cx, I2C_FLAG_AF);
149 | return 2;
150 | }
151 | }
152 | return 0;
153 | }
154 |
155 | int I2C_stop(I2C_TypeDef* I2Cx)
156 | {
157 | I2C_GenerateSTOP(I2Cx, ENABLE);
158 | return 0;
159 | }
160 |
161 | int8_t I2C_read_ack(I2C_TypeDef* I2Cx)
162 | {
163 | int8_t data;
164 |
165 | I2C_AcknowledgeConfig(I2Cx, ENABLE);
166 | while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_RECEIVED)){
167 | if (I2C_GetFlagStatus(I2Cx, I2C_FLAG_TIMEOUT)!=RESET) {
168 | I2C_ClearFlag(I2Cx, I2C_FLAG_TIMEOUT);
169 | return -127;
170 | }
171 | if(I2C_GetFlagStatus(I2Cx, I2C_FLAG_AF)!=RESET) {
172 | I2C_ClearFlag(I2Cx, I2C_FLAG_AF);
173 | return -127;
174 | }
175 | }
176 | data=I2C_ReceiveData(I2Cx);
177 |
178 | return data;
179 | }
180 |
181 | int8_t I2C_read_nack(I2C_TypeDef* I2Cx)
182 | {
183 | uint8_t data;
184 |
185 | I2C_AcknowledgeConfig(I2Cx, DISABLE);
186 | I2C_GenerateSTOP(I2Cx, ENABLE);
187 |
188 | while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_RECEIVED)){
189 | if (I2C_GetFlagStatus(I2Cx, I2C_FLAG_TIMEOUT)!=RESET) {
190 | I2C_ClearFlag(I2Cx, I2C_FLAG_TIMEOUT);
191 | return -127;
192 | }
193 | }
194 | data=I2C_ReceiveData(I2Cx);
195 |
196 | return data;
197 | }
198 |
--------------------------------------------------------------------------------
/6 - INA226/F7_INA226.c:
--------------------------------------------------------------------------------
1 | /**
2 | ********************************************************************************
3 | * @brief STM32 HAL Library for INA226 Current/Power Monitor
4 | * @date Feb 2016
5 | * @version 1.0
6 | * @author George Christidis
7 | ********************************************************************************
8 | * @details
9 | This library contains the necessary functions to initialize, read and
10 | write data to the TI INA226 Current/Power Monitor using the I2C
11 | protocol.
12 | ******************************************************************************
13 | */
14 |
15 | #include "F7_INA226.h"
16 |
17 | float32_t INA226_getBusV(I2C_HandleTypeDef *I2CHandler, uint16_t DevAddress) {
18 | return (INA226_getBusVReg(I2CHandler, DevAddress));
19 | }
20 |
21 | float32_t INA226_getCurrent(I2C_HandleTypeDef *I2CHandler, uint16_t DevAddress) {
22 | return (INA226_getCurrentReg(I2CHandler, DevAddress)*INA226_CURRENTLSB_INV);
23 | }
24 |
25 | float32_t INA226_getPower(I2C_HandleTypeDef *I2CHandler, uint16_t DevAddress) {
26 | return (INA226_getPowerReg(I2CHandler, DevAddress)*INA226_POWERLSB_INV);
27 | }
28 |
29 | uint8_t INA226_setConfig(I2C_HandleTypeDef *I2CHandler, uint16_t DevAddress, uint16_t ConfigWord) {
30 | uint8_t SentTable[3];
31 | SentTable[0] = INA226_CONFIG;
32 | SentTable[1] = (ConfigWord & 0xFF00) >> 8;
33 | SentTable[2] = (ConfigWord & 0x00FF);
34 | return HAL_I2C_Master_Transmit(I2CHandler, DevAddress, SentTable, 3, INA226_I2CTIMEOUT);
35 | }
36 |
37 | uint16_t INA226_getConfig(I2C_HandleTypeDef *I2CHandler, uint16_t DevAddress) {
38 | uint8_t SentTable[1] = {INA226_CONFIG};
39 | uint8_t ReceivedTable[2];
40 | HAL_I2C_Master_Transmit(I2CHandler,DevAddress, SentTable, 1, INA226_I2CTIMEOUT);
41 | if (HAL_I2C_Master_Receive(I2CHandler,DevAddress, ReceivedTable, 2, INA226_I2CTIMEOUT) != HAL_OK) return 0xFF;
42 | else return ((uint16_t)ReceivedTable[0]<<8 | ReceivedTable[1]);
43 | }
44 |
45 | uint16_t INA226_getShuntV(I2C_HandleTypeDef *I2CHandler, uint16_t DevAddress) {
46 | uint8_t SentTable[1] = {INA226_SHUNTV};
47 | uint8_t ReceivedTable[2];
48 | HAL_I2C_Master_Transmit(I2CHandler,DevAddress, SentTable, 1, INA226_I2CTIMEOUT);
49 | if (HAL_I2C_Master_Receive(I2CHandler,DevAddress, ReceivedTable, 2, INA226_I2CTIMEOUT) != HAL_OK) return 0xFF;
50 | else return ((uint16_t)ReceivedTable[0]<<8 | ReceivedTable[1]);
51 | }
52 |
53 | uint16_t INA226_getBusVReg(I2C_HandleTypeDef *I2CHandler, uint16_t DevAddress) {
54 | uint8_t SentTable[1] = {INA226_BUSV};
55 | uint8_t ReceivedTable[2];
56 | HAL_I2C_Master_Transmit(I2CHandler,DevAddress, SentTable, 1, INA226_I2CTIMEOUT);
57 | if (HAL_I2C_Master_Receive(I2CHandler,DevAddress, ReceivedTable, 2, INA226_I2CTIMEOUT) != HAL_OK) return 0xFF;
58 | else return ((uint16_t)ReceivedTable[0]<<8 | ReceivedTable[1]);
59 | }
60 |
61 | uint8_t INA226_setCalibrationReg(I2C_HandleTypeDef *I2CHandler, uint16_t DevAddress, uint16_t ConfigWord) {
62 | uint8_t SentTable[3];
63 | SentTable[0] = INA226_CALIB;
64 | SentTable[1] = (ConfigWord & 0xFF00) >> 8;
65 | SentTable[2] = (ConfigWord & 0x00FF);
66 | return HAL_I2C_Master_Transmit(I2CHandler, DevAddress, SentTable, 3, INA226_I2CTIMEOUT);
67 | }
68 |
69 | uint16_t INA226_getCalibrationReg(I2C_HandleTypeDef *I2CHandler, uint16_t DevAddress) {
70 | uint8_t SentTable[1] = {INA226_CALIB};
71 | uint8_t ReceivedTable[2];
72 | HAL_I2C_Master_Transmit(I2CHandler,DevAddress, SentTable, 1, INA226_I2CTIMEOUT);
73 | if (HAL_I2C_Master_Receive(I2CHandler,DevAddress, ReceivedTable, 2, INA226_I2CTIMEOUT) != HAL_OK) return 0xFF;
74 | else return ((uint16_t)ReceivedTable[0]<<8 | ReceivedTable[1]);
75 | }
76 |
77 | uint16_t INA226_getPowerReg(I2C_HandleTypeDef *I2CHandler, uint16_t DevAddress) {
78 | uint8_t SentTable[1] = {INA226_POWER};
79 | uint8_t ReceivedTable[2];
80 | HAL_I2C_Master_Transmit(I2CHandler,DevAddress, SentTable, 1, INA226_I2CTIMEOUT);
81 | if (HAL_I2C_Master_Receive(I2CHandler,DevAddress, ReceivedTable, 2, INA226_I2CTIMEOUT) != HAL_OK) return 0xFF;
82 | else return ((uint16_t)ReceivedTable[0]<<8 | ReceivedTable[1]);
83 | }
84 |
85 | uint16_t INA226_getCurrentReg(I2C_HandleTypeDef *I2CHandler, uint16_t DevAddress) {
86 | uint8_t SentTable[1] = {INA226_CURRENT};
87 | uint8_t ReceivedTable[2];
88 | HAL_I2C_Master_Transmit(I2CHandler,DevAddress, SentTable, 1, INA226_I2CTIMEOUT);
89 | if (HAL_I2C_Master_Receive(I2CHandler,DevAddress, ReceivedTable, 2, INA226_I2CTIMEOUT) != HAL_OK) return 0xFF;
90 | else return ((uint16_t)ReceivedTable[0]<<8 | ReceivedTable[1]);
91 | }
92 |
93 | uint16_t INA226_getManufID(I2C_HandleTypeDef *I2CHandler, uint16_t DevAddress) {
94 | uint8_t SentTable[1] = {INA226_MANUF_ID};
95 | uint8_t ReceivedTable[2];
96 | HAL_I2C_Master_Transmit(I2CHandler,DevAddress, SentTable, 1, INA226_I2CTIMEOUT);
97 | if (HAL_I2C_Master_Receive(I2CHandler,DevAddress, ReceivedTable, 2, INA226_I2CTIMEOUT) != HAL_OK) return 0xFF;
98 | else return ((uint16_t)ReceivedTable[0]<<8 | ReceivedTable[1]);
99 | }
100 |
101 | uint16_t INA226_getDieID(I2C_HandleTypeDef *I2CHandler, uint16_t DevAddress) {
102 | uint8_t SentTable[1] = {INA226_DIE_ID};
103 | uint8_t ReceivedTable[2];
104 | HAL_I2C_Master_Transmit(I2CHandler,DevAddress, SentTable, 1, INA226_I2CTIMEOUT);
105 | if (HAL_I2C_Master_Receive(I2CHandler,DevAddress, ReceivedTable, 2, INA226_I2CTIMEOUT) != HAL_OK) return 0xFF;
106 | else return ((uint16_t)ReceivedTable[0]<<8 | ReceivedTable[1]);
107 | }
108 |
109 | uint8_t INA226_setMaskEnable(I2C_HandleTypeDef *I2CHandler, uint16_t DevAddress, uint16_t ConfigWord) {
110 | uint8_t SentTable[3];
111 | SentTable[0] = INA226_MASK;
112 | SentTable[1] = (ConfigWord & 0xFF00) >> 8;
113 | SentTable[2] = (ConfigWord & 0x00FF);
114 | return HAL_I2C_Master_Transmit(I2CHandler, DevAddress, SentTable, 3, INA226_I2CTIMEOUT);
115 | }
116 |
117 | uint16_t INA226_getMaskEnable(I2C_HandleTypeDef *I2CHandler, uint16_t DevAddress) {
118 | uint8_t SentTable[1] = {INA226_MASK};
119 | uint8_t ReceivedTable[2];
120 | HAL_I2C_Master_Transmit(I2CHandler,DevAddress, SentTable, 1, INA226_I2CTIMEOUT);
121 | if (HAL_I2C_Master_Receive(I2CHandler,DevAddress, ReceivedTable, 2, INA226_I2CTIMEOUT) != HAL_OK) return 0xFF;
122 | else return ((uint16_t)ReceivedTable[0]<<8 | ReceivedTable[1]);
123 | }
124 |
125 | uint8_t INA226_setAlertLimit(I2C_HandleTypeDef *I2CHandler, uint16_t DevAddress, uint16_t ConfigWord) {
126 | uint8_t SentTable[3];
127 | SentTable[0] = INA226_ALERTL;
128 | SentTable[1] = (ConfigWord & 0xFF00) >> 8;
129 | SentTable[2] = (ConfigWord & 0x00FF);
130 | return HAL_I2C_Master_Transmit(I2CHandler, DevAddress, SentTable, 3, INA226_I2CTIMEOUT);
131 | }
132 |
133 | uint16_t INA226_getAlertLimit(I2C_HandleTypeDef *I2CHandler, uint16_t DevAddress) {
134 | uint8_t SentTable[1] = {INA226_ALERTL};
135 | uint8_t ReceivedTable[2];
136 | HAL_I2C_Master_Transmit(I2CHandler,DevAddress, SentTable, 1, INA226_I2CTIMEOUT);
137 | if (HAL_I2C_Master_Receive(I2CHandler,DevAddress, ReceivedTable, 2, INA226_I2CTIMEOUT) != HAL_OK) return 0xFF;
138 | else return ((uint16_t)ReceivedTable[0]<<8 | ReceivedTable[1]);
139 | }
140 |
--------------------------------------------------------------------------------
/3 - TC74 with low power/main.c:
--------------------------------------------------------------------------------
1 | /**
2 | ******************************************************************************
3 | * @brief TC74 temperature sensor example code on STM32 with stanby mode
4 | * @date May 2015
5 | * @version 1.0
6 | * @author George Christidis
7 | ******************************************************************************
8 | * @details
9 | This program reads the temperature of a TC74 connected to an STM32L152
10 | discovery board. The sensor is connected on the I2C1 pins (SCL: PB6,
11 | SDA: PB7). It returns the value to a variable named temperature which then
12 | can be sent via UART, shown on a display or through a debug session. The
13 | temperature is sampled every 5 seconds, via TIM6. After that the TC74
14 | enters standby mode until the next read.
15 | ******************************************************************************
16 | */
17 |
18 | /* Includes ------------------------------------------------------------------*/
19 |
20 | #include "stm32l1xx_usart.h"
21 | #include "stm32l1xx_rcc.h"
22 | #include "stm32l1xx_gpio.h"
23 | #include "stm32l1xx_tim.h"
24 | #include "stm32l1xx_i2c.h"
25 |
26 | #define TC74_ADDRESS 0x9A // TC74 A5 address
27 |
28 | void TC74_Config(void), TIM6_Config(void);
29 | int TC74_Read_Register(uint8_t, uint8_t), TC74_Sleep(uint8_t), TC74_WakeUp(uint8_t);
30 | int I2C_start(I2C_TypeDef *, uint8_t, uint8_t), I2C_write(I2C_TypeDef *, uint8_t), I2C_stop(I2C_TypeDef *);
31 | int8_t I2C_read_ack(I2C_TypeDef *), I2C_read_nack(I2C_TypeDef *);
32 | int temperature;
33 |
34 | typedef enum {TC74_SLEEPING, TC74_WAITING} TC74_statetypedef;
35 | TC74_statetypedef Temp_read_status=TC74_SLEEPING;
36 |
37 | int main()
38 | {
39 | TC74_Config();
40 | TIM6_Config();
41 |
42 | while(1);
43 | }
44 |
45 | void TC74_Config(void)
46 | {
47 | GPIO_InitTypeDef GPIO_InitStructure;
48 | I2C_InitTypeDef I2C_InitStructure;
49 |
50 | RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);
51 | RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
52 |
53 | GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_I2C1);
54 | GPIO_PinAFConfig(GPIOB, GPIO_PinSource7, GPIO_AF_I2C1);
55 | GPIO_StructInit(&GPIO_InitStructure);
56 | GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
57 | GPIO_InitStructure.GPIO_Speed = GPIO_Speed_40MHz;
58 | GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
59 | GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
60 | GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
61 | GPIO_Init(GPIOB, &GPIO_InitStructure);
62 |
63 | I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
64 | I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
65 | I2C_InitStructure.I2C_ClockSpeed = 10000;
66 | I2C_InitStructure.I2C_Mode = I2C_Mode_SMBusHost;
67 | I2C_InitStructure.I2C_OwnAddress1 = 0x00;
68 | I2C_Init(I2C1, &I2C_InitStructure);
69 | I2C_Cmd(I2C1, ENABLE);
70 | }
71 |
72 | int TC74_Read_Register(uint8_t TC74address, uint8_t reg)
73 | {
74 | int8_t data1, data2;
75 |
76 | if(I2C_start(I2C1, TC74address, I2C_Direction_Transmitter)>0) {
77 | return -127;
78 | }
79 | if(I2C_write(I2C1, reg)>0) return -127;
80 | if(I2C_stop(I2C1)==1) return -127;
81 |
82 | if(I2C_start(I2C1, TC74address, I2C_Direction_Receiver)>0) {
83 | return -127;
84 | }
85 | data1 = I2C_read_ack(I2C1);
86 | data2 = I2C_read_nack(I2C1);
87 |
88 | return data1;
89 | }
90 |
91 | int TC74_WakeUp(uint8_t TC74address)
92 | {
93 | if(I2C_start(I2C1, TC74address, I2C_Direction_Transmitter)>0) {
94 | return -127;
95 | }
96 | if(I2C_write(I2C1, 0x01)>0) return -127;
97 | if(I2C_write(I2C1, 0x00)>0) return -127;
98 | if(I2C_stop(I2C1)==1) return -127;
99 | return 0;
100 | }
101 |
102 | int TC74_Sleep(uint8_t TC74address)
103 | {
104 | if(I2C_start(I2C1, TC74address, I2C_Direction_Transmitter)>0) {
105 | return -127;
106 | }
107 | if(I2C_write(I2C1, 0x01)>0) return -127;
108 | if(I2C_write(I2C1, 0x80)>0) return -127;
109 | if(I2C_stop(I2C1)==1) return -127;
110 | return 0;
111 | }
112 |
113 | int I2C_start(I2C_TypeDef* I2Cx, uint8_t address, uint8_t direction)
114 | {
115 | while(I2C_GetFlagStatus(I2Cx, I2C_FLAG_BUSY));
116 |
117 | I2C_GenerateSTART(I2Cx, ENABLE);
118 |
119 | while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT)){
120 | if(I2C_GetFlagStatus(I2Cx, I2C_FLAG_TIMEOUT)!=RESET) {
121 | I2C_ClearFlag(I2Cx, I2C_FLAG_TIMEOUT);
122 | return 1;
123 | }
124 | if(I2C_GetFlagStatus(I2Cx, I2C_FLAG_AF)!=RESET) {
125 | I2C_ClearFlag(I2Cx, I2C_FLAG_AF);
126 | return 2;
127 | }
128 | }
129 |
130 | I2C_Send7bitAddress(I2Cx, address, direction);
131 |
132 | if (direction== I2C_Direction_Transmitter) {
133 | while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)){
134 | if (I2C_GetFlagStatus(I2Cx, I2C_FLAG_TIMEOUT)!=RESET) {
135 | I2C_ClearFlag(I2Cx, I2C_FLAG_TIMEOUT);
136 | return 1;
137 | }
138 | if(I2C_GetFlagStatus(I2Cx, I2C_FLAG_AF)!=RESET) {
139 | I2C_ClearFlag(I2Cx, I2C_FLAG_AF);
140 | return 2;
141 | }
142 | }
143 | }
144 |
145 | else if(direction == I2C_Direction_Receiver) {
146 | while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)){
147 | if (I2C_GetFlagStatus(I2Cx, I2C_FLAG_TIMEOUT)!=RESET) {
148 | I2C_ClearFlag(I2Cx, I2C_FLAG_TIMEOUT);
149 | return 3;
150 | }
151 | if(I2C_GetFlagStatus(I2Cx, I2C_FLAG_AF)!=RESET) {
152 | I2C_ClearFlag(I2Cx, I2C_FLAG_AF);
153 | return 4;
154 | }
155 | }
156 | }
157 | return 0;
158 | }
159 |
160 | int I2C_write(I2C_TypeDef* I2Cx, uint8_t data)
161 | {
162 | I2C_SendData(I2Cx, data);
163 |
164 | while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED)){
165 | if (I2C_GetFlagStatus(I2Cx, I2C_FLAG_TIMEOUT)!=RESET) {
166 | I2C_ClearFlag(I2Cx, I2C_FLAG_TIMEOUT);
167 | return 1;
168 | }
169 | if(I2C_GetFlagStatus(I2Cx, I2C_FLAG_AF)!=RESET) {
170 | I2C_ClearFlag(I2Cx, I2C_FLAG_AF);
171 | return 2;
172 | }
173 | }
174 | return 0;
175 | }
176 |
177 | int I2C_stop(I2C_TypeDef* I2Cx)
178 | {
179 | I2C_GenerateSTOP(I2Cx, ENABLE);
180 | return 0;
181 | }
182 |
183 | int8_t I2C_read_ack(I2C_TypeDef* I2Cx)
184 | {
185 | int8_t data;
186 |
187 | I2C_AcknowledgeConfig(I2Cx, ENABLE);
188 | while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_RECEIVED)){
189 | if (I2C_GetFlagStatus(I2Cx, I2C_FLAG_TIMEOUT)!=RESET) {
190 | I2C_ClearFlag(I2Cx, I2C_FLAG_TIMEOUT);
191 | return -127;
192 | }
193 | if(I2C_GetFlagStatus(I2Cx, I2C_FLAG_AF)!=RESET) {
194 | I2C_ClearFlag(I2Cx, I2C_FLAG_AF);
195 | return -127;
196 | }
197 | }
198 | data=I2C_ReceiveData(I2Cx);
199 |
200 | return data;
201 | }
202 |
203 | int8_t I2C_read_nack(I2C_TypeDef* I2Cx)
204 | {
205 | uint8_t data;
206 |
207 | I2C_AcknowledgeConfig(I2Cx, DISABLE);
208 | I2C_GenerateSTOP(I2Cx, ENABLE);
209 |
210 | while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_RECEIVED)){
211 | if (I2C_GetFlagStatus(I2Cx, I2C_FLAG_TIMEOUT)!=RESET) {
212 | I2C_ClearFlag(I2Cx, I2C_FLAG_TIMEOUT);
213 | return -127;
214 | }
215 | }
216 | data=I2C_ReceiveData(I2Cx);
217 |
218 | return data;
219 | }
220 |
221 | void TIM6_Config(void)
222 | {
223 | TIM_TimeBaseInitTypeDef timerInitStructure;
224 | NVIC_InitTypeDef NVIC_InitStructure;
225 |
226 | RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, ENABLE);
227 |
228 | timerInitStructure.TIM_Prescaler=1000;
229 | timerInitStructure.TIM_CounterMode=TIM_CounterMode_Up;
230 | timerInitStructure.TIM_Period=32000;
231 | timerInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;
232 | TIM_TimeBaseInit(TIM6, &timerInitStructure);
233 | TIM_Cmd(TIM6, ENABLE);
234 |
235 | NVIC_InitStructure.NVIC_IRQChannel = TIM6_IRQn;
236 | NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
237 | NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 8;
238 | NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
239 | NVIC_Init(&NVIC_InitStructure);
240 | TIM_ITConfig(TIM6, TIM_IT_Update, ENABLE);
241 | }
242 |
243 | void TIM6_IRQHandler(void)
244 | {
245 | if (TIM_GetFlagStatus(TIM6, TIM_IT_Update)!=RESET) {
246 | TIM_Cmd(TIM6, DISABLE);
247 |
248 | if (Temp_read_status==TC74_SLEEPING) {
249 |
250 | TC74_WakeUp(TC74_ADDRESS);
251 | TIM6->PSC = 5000;
252 | Temp_read_status=TC74_WAITING;
253 | }
254 |
255 | else {
256 | temperature=TC74_Read_Register(TC74_ADDRESS,0x00);
257 | TC74_Sleep(TC74_ADDRESS);
258 |
259 | TIM6->PSC = 500;
260 | Temp_read_status=TC74_SLEEPING;
261 | }
262 |
263 | TIM6->CNT=0;
264 | TIM_Cmd(TIM6, ENABLE);
265 | TIM_ClearITPendingBit(TIM6, TIM_IT_Update);
266 | }
267 | }
--------------------------------------------------------------------------------
/8 - F4 Dot Matrix Controller/MatrixController.c:
--------------------------------------------------------------------------------
1 | /**
2 | ********************************************************************************
3 | * @brief STM32 F429 Discovery Dot Matrix Controller
4 | * @date Dec 2016
5 | * @version 1.0
6 | * @author George Christidis
7 | ********************************************************************************
8 | * @details
9 | This example shows how to drive an 64x32 Dot Matrix Display using
10 | an STM32F429 Discovery board. It uses UART to get new frames and stores
11 | them in two different memory banks.
12 | ******************************************************************************
13 | */
14 |
15 |
16 | #include "stm32f4xx.h"
17 | #include
18 |
19 | #include "defines.h"
20 | #include "attributes.h"
21 | #include "stm32f4xx_usart.h"
22 | #include "tm_stm32f4_delay.h"
23 | #include "stm32f4xx_exti.h"
24 | #include "stm32f4xx_syscfg.h"
25 |
26 | uint8_t rowcounter=0;
27 | uint8_t colcounter=0;
28 | int8_t pwmindex=0;
29 | uint8_t delaybrightness=100-BRIGHTNESS;
30 | uint8_t brightvalue=50; //if needed to dim display even more
31 | uint8_t EN=1;
32 | volatile uint8_t *readmemory, *writememory;
33 | volatile uint8_t mem1[ROWS*COLUMNS*3], mem2[ROWS*COLUMNS*3];
34 | void InitMatrixPorts(void), InitUARTDMA(void), InitDiscoButton(void);
35 |
36 | int main(void) {
37 | int i;
38 | extern uint8_t initimage[];
39 |
40 | SystemInit();
41 | TM_DELAY_Init();
42 |
43 | //Memory Banks//
44 | readmemory = mem1;
45 | writememory = mem2;
46 |
47 | InitDiscoButton();
48 | InitMatrixPorts();
49 | InitUARTDMA();
50 |
51 | for (i=0; i<6144; i++) {
52 | mem1[i] = initimage[i];
53 | }
54 |
55 | while(1) {
56 | if (EN==1)
57 | {
58 | for (pwmindex = 7; pwmindex>=(7-(COLDEPTH-1)); pwmindex--){
59 | for (rowcounter=0 ; rowcounter<(ROWS/2) ; rowcounter++) {
60 | GPIO_SetBits(OEPORT,OEPIN);
61 | for (colcounter=0 ; colcounter> pwmindex) & 0x01)==1) GPIO_SetBits(R1PORT,R1PIN);
64 | else GPIO_ResetBits(R1PORT,R1PIN);
65 | if (((readmemory[rowcounter*COLUMNS*3+colcounter*3+1] >> pwmindex) & 0x01)==1) GPIO_SetBits(G1PORT,G1PIN);
66 | else GPIO_ResetBits(G1PORT,G1PIN);
67 | if (((readmemory[rowcounter*COLUMNS*3+colcounter*3+2] >> pwmindex) & 0x01)==1) GPIO_SetBits(B1PORT,B1PIN);
68 | else GPIO_ResetBits(B1PORT,B1PIN);
69 | if (((readmemory[(ROWS*COLUMNS/2)*3+rowcounter*COLUMNS*3+colcounter*3+0] >> pwmindex) & 0x01)==1) GPIO_SetBits(R2PORT,R2PIN);
70 | else GPIO_ResetBits(R2PORT,R2PIN);
71 | if (((readmemory[(ROWS*COLUMNS/2)*3+rowcounter*COLUMNS*3+colcounter*3+1] >> pwmindex) & 0x01)==1) GPIO_SetBits(G2PORT,G2PIN);
72 | else GPIO_ResetBits(G2PORT,G2PIN);
73 | if (((readmemory[(ROWS*COLUMNS/2)*3+rowcounter*COLUMNS*3+colcounter*3+2] >> pwmindex) & 0x01)==1) GPIO_SetBits(B2PORT,B2PIN);
74 | else GPIO_ResetBits(B2PORT,B2PIN);
75 | GPIO_SetBits(CLKPORT,CLKPIN);
76 | if (colcounter>brightvalue) GPIO_ResetBits(OEPORT,OEPIN);
77 | }
78 |
79 | GPIO_SetBits(OEPORT,OEPIN);
80 | Delay(1);
81 | GPIO_SetBits(LEPORT,LEPIN);
82 | if ((rowcounter & 0x01)==0x01) GPIO_SetBits(ROW0PORT,ROW0PIN); else GPIO_ResetBits(ROW0PORT,ROW0PIN);
83 | if ((rowcounter & 0x02)==0x02) GPIO_SetBits(ROW1PORT,ROW1PIN); else GPIO_ResetBits(ROW1PORT,ROW1PIN);
84 | if ((rowcounter & 0x04)==0x04) GPIO_SetBits(ROW2PORT,ROW2PIN); else GPIO_ResetBits(ROW2PORT,ROW2PIN);
85 | if ((rowcounter & 0x08)==0x08) GPIO_SetBits(ROW3PORT,ROW3PIN); else GPIO_ResetBits(ROW3PORT,ROW3PIN);
86 | GPIO_ResetBits(LEPORT,LEPIN);
87 | Delay(delaybrightness);
88 | Delay(1);
89 | GPIO_ResetBits(OEPORT,OEPIN);
90 | Delay(59*(pwmindex-(8-COLDEPTH)+1)*(pwmindex-(8-COLDEPTH)+1)-59);
91 | }
92 | }
93 | }
94 | else GPIO_SetBits(OEPORT,OEPIN);
95 | }
96 | }
97 |
98 | void EXTI0_IRQHandler() {
99 | if (EXTI_GetITStatus(EXTI_Line0) == SET){
100 | if (EN==1) EN=0;
101 | else EN=1;
102 | }
103 | EXTI_ClearITPendingBit(EXTI_Line0);
104 | }
105 |
106 | void DMA2_Stream5_IRQHandler(void)
107 | {
108 | volatile uint8_t *temppointer;
109 | if(DMA_GetITStatus(DMA2_Stream5, DMA_IT_TCIF5) == SET)
110 | {
111 | temppointer = readmemory;
112 | readmemory = writememory;
113 | writememory = temppointer;
114 | DMA_Cmd(DMA2_Stream5, DISABLE);
115 | DMA2_Stream5->M0AR = (uint32_t)writememory;
116 | DMA_Cmd(DMA2_Stream5, ENABLE);
117 | DMA_ClearITPendingBit(DMA2_Stream5, DMA_IT_TCIF5);
118 | }
119 | }
120 |
121 | void InitMatrixPorts() {
122 | GPIO_InitTypeDef GPIO_InitStructure;
123 |
124 | RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOD | RCC_AHB1Periph_GPIOG, ENABLE);
125 |
126 | GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
127 | GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
128 | GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
129 | GPIO_InitStructure.GPIO_Speed = GPIO_High_Speed;
130 | GPIO_InitStructure.GPIO_Pin = R1PIN;
131 | GPIO_Init(R1PORT, &GPIO_InitStructure);
132 | GPIO_InitStructure.GPIO_Pin = G1PIN;
133 | GPIO_Init(G1PORT, &GPIO_InitStructure);
134 | GPIO_InitStructure.GPIO_Pin = B1PIN;
135 | GPIO_Init(B1PORT, &GPIO_InitStructure);
136 | GPIO_InitStructure.GPIO_Pin = R2PIN;
137 | GPIO_Init(R2PORT, &GPIO_InitStructure);
138 | GPIO_InitStructure.GPIO_Pin = G2PIN;
139 | GPIO_Init(G2PORT, &GPIO_InitStructure);
140 | GPIO_InitStructure.GPIO_Pin = ROW3PIN;
141 | GPIO_Init(ROW3PORT, &GPIO_InitStructure);
142 | GPIO_InitStructure.GPIO_Pin = ROW2PIN;
143 | GPIO_Init(ROW2PORT, &GPIO_InitStructure);
144 | GPIO_InitStructure.GPIO_Pin = ROW1PIN;
145 | GPIO_Init(ROW1PORT, &GPIO_InitStructure);
146 | GPIO_InitStructure.GPIO_Pin = ROW0PIN;
147 | GPIO_Init(ROW0PORT, &GPIO_InitStructure);
148 | GPIO_InitStructure.GPIO_Pin = B2PIN;
149 | GPIO_Init(B2PORT, &GPIO_InitStructure);
150 | GPIO_InitStructure.GPIO_Pin = OEPIN;
151 | GPIO_Init(OEPORT, &GPIO_InitStructure);
152 | GPIO_InitStructure.GPIO_Pin = LEPIN;
153 | GPIO_Init(LEPORT, &GPIO_InitStructure);
154 | GPIO_InitStructure.GPIO_Pin = CLKPIN;
155 | GPIO_Init(CLKPORT, &GPIO_InitStructure);
156 | }
157 |
158 | void InitUARTDMA() {
159 |
160 | //UART 1 PB7 RX
161 | //DMA2 Channel 4 Stream 5
162 | USART_InitTypeDef USART_InitStructure;
163 | DMA_InitTypeDef DMA_InitStructure;
164 | GPIO_InitTypeDef GPIO_InitStructure;
165 | NVIC_InitTypeDef NVIC_InitStructure;
166 |
167 | RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
168 | RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
169 | RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);
170 |
171 | GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
172 | GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
173 | GPIO_InitStructure.GPIO_Speed = GPIO_Fast_Speed;
174 | GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
175 | GPIO_Init(GPIOB, &GPIO_InitStructure);
176 | GPIO_PinAFConfig(GPIOB,GPIO_PinSource7, GPIO_AF_USART1);
177 |
178 | USART_InitStructure.USART_BaudRate = 115200;
179 | USART_InitStructure.USART_Mode = USART_Mode_Rx;
180 | USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
181 | USART_InitStructure.USART_Parity = USART_Parity_No;
182 | USART_Init(USART1, &USART_InitStructure);
183 | USART_Cmd(USART1, ENABLE);
184 |
185 | DMA_InitStructure.DMA_Channel = DMA_Channel_4;
186 | DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&USART1->DR;
187 | DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)writememory;
188 | DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
189 | DMA_InitStructure.DMA_BufferSize = ROWS*COLUMNS*3;
190 | DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
191 | DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
192 | DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
193 | DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
194 | DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
195 | DMA_InitStructure.DMA_Priority = DMA_Priority_High;
196 | DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
197 | DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;
198 | DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
199 | DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
200 | DMA_Init(DMA2_Stream5, &DMA_InitStructure);
201 | DMA_Cmd(DMA2_Stream5, ENABLE);
202 | USART_DMACmd(USART1, USART_DMAReq_Rx, ENABLE);
203 |
204 | NVIC_InitStructure.NVIC_IRQChannel = DMA2_Stream5_IRQn;
205 | NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
206 | NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
207 | NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
208 | NVIC_Init(&NVIC_InitStructure);
209 |
210 | DMA_ITConfig(DMA2_Stream5, DMA_IT_TC, ENABLE);
211 | }
212 |
213 | void InitDiscoButton(void)
214 | {
215 | GPIO_InitTypeDef GPIO_InitStructure;
216 | EXTI_InitTypeDef EXTI_InitStructure;
217 | NVIC_InitTypeDef NVIC_InitStructure;
218 |
219 | RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
220 | RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
221 |
222 | GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
223 | GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
224 | GPIO_InitStructure.GPIO_Speed = GPIO_Low_Speed;
225 | GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
226 | GPIO_Init(GPIOA, &GPIO_InitStructure);
227 |
228 | EXTI_InitStructure.EXTI_Line = EXTI_Line0;
229 | EXTI_InitStructure.EXTI_LineCmd = ENABLE;
230 | EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
231 | EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
232 | EXTI_Init(&EXTI_InitStructure);
233 |
234 | SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA, EXTI_PinSource0);
235 |
236 | NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;
237 | NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
238 | NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
239 | NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
240 | NVIC_Init(&NVIC_InitStructure);
241 | }
242 |
--------------------------------------------------------------------------------
/8 - F4 Dot Matrix Controller/initimage.c:
--------------------------------------------------------------------------------
1 | #include "stm32f4xx.h"
2 |
3 | const uint8_t initimage[]={254,131,0,255,158,0,255,182,0,255,204,0,254,225,0,255,239,0,254,251,0,243,253,0,230,252,4,213,253,7,194,249,7,169,245,12,147,238,13,123,228,14,103,216,22,78,207,26,56,197,31,36,191,38,19,184,45,5,182,52,0,179,65,0,181,74,0,185,84,2,192,104,0,198,119,0,205,140,0,212,161,0,222,181,0,233,203,0,234,225,0,233,240,0,233,255,2,222,255,0,199,248,0,169,231,2,134,217,0,110,199,0,89,189,0,70,181,0,54,170,0,39,160,0,23,155,2,12,146,0,3,148,12,0,141,33,0,144,52,0,145,75,0,153,100,0,158,128,0,164,166,0,174,202,0,186,230,0,188,252,0,197,255,13,203,254,21,201,255,33,206,255,51,212,255,80,215,253,122,226,255,167,235,254,208,244,255,243,252,255,255,255,255,119,0,255,145,0,255,170,0,255,195,0,254,215,0,254,232,0,255,245,3,252,251,0,240,253,0,223,252,4,203,253,6,183,247,11,159,242,14,136,231,17,109,223,22,89,211,24,64,202,28,44,194,34,28,187,41,11,182,44,0,179,59,0,182,67,2,184,84,0,188,96,0,195,111,2,202,129,0,209,146,0,215,164,0,227,192,0,233,219,0,235,234,0,233,250,0,231,253,0,210,253,0,184,242,0,150,227,3,118,207,0,99,192,0,81,186,0,61,171,0,46,165,0,32,155,0,15,146,0,7,144,7,2,144,21,0,142,43,0,146,63,0,149,86,0,155,112,2,161,144,0,168,185,0,182,216,0,189,246,0,196,252,6,195,255,16,203,255,28,203,255,41,207,255,64,211,255,101,221,253,146,228,255,188,239,254,229,251,255,255,255,254,110,0,255,132,3,254,158,0,255,182,0,254,206,2,255,224,0,254,239,0,255,252,2,245,252,0,230,252,6,212,252,6,192,252,6,171,243,9,149,237,15,122,228,16,102,215,21,78,205,27,56,197,31,36,191,37,19,186,46,6,179,53,0,180,65,0,181,74,0,187,88,0,192,106,0,197,121,0,206,139,0,213,159,0,222,181,0,231,205,0,234,227,0,235,242,0,234,253,0,223,255,0,199,248,0,167,235,0,134,215,0,110,202,0,90,187,0,71,179,2,53,171,0,39,160,23,30,136,56,37,83,82,50,12,85,49,17,83,51,13,72,32,84,80,4,138,100,0,158,126,0,164,164,2,173,201,0,183,230,0,194,255,0,196,217,25,164,163,42,111,83,51,13,80,50,14,85,49,13,137,70,88,204,131,176,255,210,241,255,244,252,254,96,0,254,119,2,239,136,5,188,123,5,82,50,12,83,51,12,83,50,15,115,89,12,185,177,4,83,49,14,137,138,11,202,252,7,180,249,10,134,192,10,82,50,12,83,50,15,83,51,13,81,51,13,83,49,14,84,50,15,83,51,13,84,48,14,84,49,17,83,51,13,79,64,21,6,187,108,79,66,31,83,51,13,80,50,14,71,100,70,7,225,211,0,233,235,0,233,250,0,232,255,21,185,220,83,51,12,84,48,12,83,51,13,54,72,108,0,80,185,0,62,175,23,45,146,82,50,12,84,50,12,84,50,13,83,51,13,82,49,14,81,52,12,81,46,44,88,3,148,114,0,158,147,0,169,186,0,180,215,0,189,179,26,134,83,50,15,84,50,13,83,49,14,83,51,13,83,49,12,83,49,12,82,49,14,183,127,154,255,227,249,255,82,3,227,99,0,100,55,13,83,51,13,84,50,15,81,51,15,83,50,15,84,50,13,82,49,14,83,51,13,134,124,9,212,250,7,195,250,8,135,171,13,83,50,15,83,51,12,83,51,13,82,49,14,83,50,15,83,49,12,83,49,12,83,50,15,82,50,12,84,50,13,83,50,15,41,146,79,81,52,12,82,48,13,84,50,12,80,50,14,46,172,150,0,235,226,0,235,246,0,233,255,64,123,129,84,52,14,80,50,12,85,49,15,77,59,59,0,90,187,0,71,177,61,52,83,84,50,15,84,50,15,80,52,13,82,50,12,85,49,15,81,52,12,83,50,15,80,26,102,101,0,159,126,0,162,169,0,177,202,0,186,111,45,57,83,51,13,84,51,16,82,49,14,82,49,16,84,50,13,83,50,15,81,51,15,96,56,31,253,212,244,255,68,4,128,61,9,80,50,12,84,50,13,83,50,15,83,49,11,84,50,13,81,51,13,85,49,13,83,49,12,132,125,11,218,253,3,201,251,6,142,174,13,84,50,12,84,50,15,84,50,13,84,50,15,83,51,13,82,49,16,83,50,15,87,49,13,81,51,13,83,49,12,83,49,12,25,167,85,74,80,36,84,51,16,83,49,12,85,49,17,62,129,98,0,234,217,0,233,237,5,225,239,85,51,16,80,51,11,84,50,13,82,49,16,58,80,119,0,99,195,0,80,183,60,55,87,83,51,13,49,40,107,2,16,151,0,6,149,53,29,89,84,50,15,83,51,13,75,37,76,89,0,153,115,0,161,145,2,170,185,0,175,145,33,105,83,51,13,189,30,133,255,18,200,253,29,203,219,46,172,83,51,13,83,51,12,83,51,13,238,172,218,254,58,0,80,50,16,84,50,13,83,48,18,179,110,6,255,184,0,254,206,0,246,215,2,153,131,9,84,52,14,150,136,5,231,253,7,213,253,9,145,176,10,83,49,12,107,130,14,122,226,19,96,200,17,83,49,14,82,52,16,71,99,22,18,185,45,6,181,54,83,50,17,82,50,12,30,158,73,0,191,105,76,78,41,84,48,12,81,51,15,82,49,16,7,224,197,0,236,230,43,176,173,81,51,13,83,50,15,83,49,12,51,115,143,0,131,213,0,108,198,0,89,191,0,73,177,0,53,169,0,38,159,0,24,150,0,11,147,31,19,121,83,49,12,83,50,15,71,29,93,77,0,149,99,0,157,129,0,163,168,0,173,203,0,186,233,0,192,255,0,198,255,13,201,255,20,202,254,34,204,128,50,72,82,52,16,83,49,14,229,144,203,255,46,0,97,52,11,84,50,13,82,52,16,244,142,0,254,172,2,255,195,0,255,216,0,255,233,0,255,247,0,252,251,0,237,251,6,222,251,3,147,166,12,83,50,15,114,146,13,134,231,14,106,204,19,84,50,13,83,49,12,74,101,24,27,186,40,11,181,49,83,51,13,83,50,17,33,155,68,0,190,95,79,64,25,81,51,13,71,93,55,85,51,14,41,172,141,0,234,219,65,128,120,82,50,11,70,101,95,84,50,13,58,112,138,0,150,223,0,118,206,0,98,195,0,80,183,0,61,173,0,45,164,0,29,155,0,18,147,46,31,96,84,50,15,83,51,12,50,11,128,67,0,148,88,2,155,115,0,161,149,0,171,184,0,182,219,0,188,245,0,197,255,7,199,253,17,203,253,29,205,102,50,39,83,50,15,112,59,55,254,146,231,252,38,0,201,55,4,82,50,12,85,51,14,100,57,14,187,117,5,206,148,4,255,205,0,255,226,0,255,241,0,253,252,2,245,252,0,230,252,6,150,165,10,84,50,13,121,147,12,144,236,13,117,208,19,84,50,12,80,50,16,77,102,18,36,191,38,18,183,45,78,63,20,84,50,15,30,155,61,0,186,92,83,51,13,81,51,17,47,147,95,84,50,13,61,125,90,7,223,199,79,70,41,65,116,109,65,116,111,83,50,15,56,122,136,0,166,234,0,132,214,0,107,201,0,90,189,0,70,176,5,53,163,65,47,69,84,50,13,85,49,15,75,45,43,38,15,121,32,0,143,52,0,145,76,0,153,102,0,159,127,0,163,168,0,176,204,0,187,234,0,193,255,0,197,254,15,202,199,35,148,84,50,12,84,50,13,195,73,156,255,124,226,255,27,0,254,48,0,237,70,2,187,75,3,115,61,14,82,50,12,83,51,13,81,51,13,99,68,14,187,165,4,255,245,0,250,251,0,235,254,2,206,232,3,155,176,13,164,218,10,156,242,13,130,212,14,83,49,12,84,51,16,78,102,18,42,194,33,28,186,40,46,138,37,46,128,43,0,181,71,0,185,82,84,48,14,81,51,15,43,152,94,69,94,55,80,50,14,43,172,141,81,51,13,48,165,159,58,143,140,84,51,16,63,117,129,0,183,241,0,147,224,0,116,207,0,98,195,0,79,184,7,60,164,83,50,15,83,49,12,84,51,16,83,51,12,63,36,71,31,3,140,43,0,145,62,0,148,90,0,158,114,0,160,148,0,170,184,0,179,217,0,192,245,0,194,217,20,162,83,50,15,83,50,15,185,48,136,255,66,214,255,102,219,254,22,0,255,36,2,254,57,2,253,84,0,255,109,0,255,134,0,220,136,4,164,115,12,83,50,15,84,51,16,128,104,8,255,253,2,244,250,4,228,253,4,212,254,7,191,250,10,170,244,11,140,219,16,82,49,16,84,50,13,82,105,17,55,198,31,35,190,37,17,185,48,2,182,56,0,179,62,7,174,69,83,50,15,83,51,10,31,167,101,48,146,95,83,50,15,80,66,37,84,52,13,13,216,210,58,143,140,86,47,16,66,112,110,0,197,246,0,167,234,0,133,216,0,108,197,0,89,189,0,69,178,0,54,169,7,39,152,52,39,93,80,50,12,81,51,13,60,34,82,33,0,145,57,0,150,77,0,151,101,0,158,130,0,164,167,0,175,203,0,187,182,23,139,83,51,13,84,50,15,188,38,138,255,33,206,255,52,209,254,84,217,237,18,0,83,51,13,129,51,12,244,70,0,255,95,0,255,123,0,255,148,0,255,172,0,155,112,8,83,48,16,82,52,14,208,195,5,251,251,3,237,251,5,219,251,4,202,254,4,180,248,7,148,221,10,84,52,14,79,49,13,84,107,17,61,202,28,45,195,36,26,185,39,10,182,48,0,180,59,18,167,67,82,50,11,84,49,17,29,166,96,14,188,117,83,51,12,84,52,14,72,98,69,2,234,221,55,142,134,84,50,12,68,114,112,0,209,248,0,181,240,0,150,223,0,119,206,0,98,191,0,80,185,0,60,172,3,45,165,0,28,154,76,46,46,84,50,15,79,46,31,25,0,141,42,0,146,66,0,149,91,0,157,115,0,158,150,0,172,147,24,128,85,49,13,82,50,12,208,24,154,255,17,204,255,28,203,253,42,209,255,67,211,218,21,4,81,51,15,84,50,13,130,50,13,219,76,6,255,109,0,254,136,2,228,143,0,100,63,10,83,50,15,81,51,15,187,170,4,255,252,0,245,252,0,229,254,4,212,250,7,192,249,10,159,225,14,83,51,13,85,50,12,86,109,19,75,207,27,55,196,32,33,191,36,19,181,44,5,181,56,15,165,58,83,50,15,84,52,14,29,161,86,2,199,127,48,146,97,77,67,32,32,188,151,0,231,207,56,142,129,81,51,13,70,101,93,0,219,255,0,197,247,0,165,231,0,130,213,0,109,199,0,87,188,0,70,176,0,52,167,2,36,160,75,47,43,83,49,14,84,51,16,13,2,143,34,0,142,55,0,148,76,0,153,104,0,161,110,27,107,83,50,15,106,44,55,210,11,166,255,0,196,255,13,203,255,24,202,255,35,206,254,53,211,221,14,6,85,49,15,83,51,13,84,52,13,83,49,14,81,51,13,84,50,13,83,49,14,83,50,15,82,50,12,83,50,15,209,185,0,255,247,0,250,252,3,229,242,2,109,91,15,83,50,15,83,51,12,83,49,11,84,50,15,83,51,13,83,49,12,85,51,16,68,120,22,25,187,40,36,155,39,83,50,15,82,50,12,83,51,13,82,50,12,37,156,88,0,203,134,0,208,150,0,218,170,63,126,99,83,51,13,83,49,12,84,52,13,76,84,73,5,201,243,0,182,239,0,150,223,0,116,205,0,97,194,0,80,187,0,62,175,47,46,112,84,50,12,84,50,13,80,47,28,6,0,143,25,0,146,44,0,143,66,0,150,88,29,97,82,49,14,84,50,15,83,50,17,82,50,12,84,50,13,83,50,15,84,50,15,83,50,15,229,45,179,218,15,0,82,50,12,84,51,18,82,50,12,84,50,12,84,50,13,83,49,14,81,51,13,84,50,15,84,48,12,155,117,8,254,225,0,255,240,2,255,253,0,215,223,2,83,51,13,82,50,12,83,51,13,82,52,16,84,50,13,83,51,13,84,50,13,83,49,14,80,78,17,33,190,37,55,133,34,80,50,14,82,52,14,83,49,14,88,50,14,58,119,60,0,199,122,3,208,143,0,215,158,74,85,53,84,50,12,84,50,13,82,50,12,84,50,13,14,203,232,24,173,216,81,51,13,84,50,15,84,50,13,82,50,11,83,49,12,82,52,14,83,51,13,82,49,14,54,35,91,0,3,146,17,0,145,32,3,145,65,18,114,84,50,13,83,51,13,84,52,13,82,50,12,83,48,16,84,50,12,82,49,14,84,50,13,83,50,15,207,42,162,246,6,5,83,50,15,113,47,12,178,42,4,84,50,15,83,51,13,83,50,17,84,50,13,140,84,10,198,134,2,255,196,0,255,219,3,255,235,0,253,247,0,242,242,4,111,89,13,84,50,15,82,49,14,84,50,15,82,49,14,84,48,12,81,51,15,84,50,13,76,124,22,43,193,34,44,158,36,85,49,13,83,49,12,84,51,18,81,52,12,36,151,76,0,196,114,0,201,131,0,209,152,62,122,86,82,50,12,84,49,17,81,51,15,75,87,73,7,219,243,31,174,206,82,50,12,84,51,16,82,49,14,85,49,13,84,50,12,82,49,14,84,50,15,72,46,57,5,19,142,0,6,144,8,0,143,26,0,145,54,11,127,80,52,13,84,49,17,82,50,12,84,50,13,84,50,15,80,50,12,84,50,13,81,51,13,85,49,15,218,37,168,255,11,11,254,0,0,255,4,0,255,20,2,255,39,0,254,60,0,255,84,0,255,110,0,255,135,0,254,160,0,255,187,0,255,207,0,255,227,3,255,241,0,255,252,0,243,252,0,230,252,3,208,252,7,191,248,9,167,243,11,144,234,14,120,225,18,96,216,22,77,206,27,52,197,32,32,190,41,18,185,45,5,181,54,0,180,63,2,181,79,0,187,90,2,191,107,0,199,122,0,206,141,0,214,160,0,223,184,0,233,206,0,233,230,0,233,247,0,233,255,3,220,255,28,165,207,55,107,129,85,49,15,83,51,13,84,51,10,77,51,36,49,50,114,0,37,159,0,22,149,0,11,149,4,3,143,15,0,143,35,0,146,53,0,149,80,0,152,105,0,160,131,0,166,170,0,175,205,0,186,232,0,193,255,0,196,255,13,201,255,22,202,255,15,16,253,3,4,254,0,0,254,12,0,254,31,0,255,49,0,255,72,0,255,97,0,254,124,0,255,149,0,255,171,0,255,197,0,253,219,0,255,235,0,255,246,0,251,252,0,237,252,3,220,252,3,201,253,7,180,247,10,157,237,14,133,229,17,106,220,19,89,211,25,64,202,31,41,193,33,24,186,41,10,181,53,0,180,61,0,182,68,0,184,83,0,190,97,0,196,117,2,202,137,0,210,149,0,216,172,0,229,196,0,233,217,0,235,235,0,234,251,0,230,254,0,210,251,0,178,242,0,147,222,0,116,205,0,97,191,0,77,185,0,61,173,0,44,163,0,29,154,0,17,149,0,7,141,9,0,148,22,0,142,46,0,146,68,0,152,91,0,155,117,0,162,151,0,170,189,0,182,223,0,191,247,0,195,254,7,199,254,19,202,255,21,21,255,10,9,254,0,0,254,5,0,254,22,0,255,38,0,255,61,0,255,85,0,255,112,0,255,136,0,255,162,0,255,187,0,236,191,0,163,139,5,84,51,16,85,49,15,83,49,14,84,51,16,81,51,15,81,51,13,153,215,10,144,236,13,122,226,19,95,215,19,72,206,25,53,198,31,69,107,20,76,75,19,2,181,55,0,181,63,0,183,79,3,184,89,0,193,106,0,200,124,0,207,142,49,151,111,77,69,33,83,50,15,68,116,102,15,216,224,0,234,253,0,220,255,0,195,246,0,163,232,46,96,145,74,58,58,83,50,15,82,49,14,52,52,104,0,36,159,2,21,152,0,10,147,4,2,145,15,0,143,34,0,143,54,0,146,79,0,153,102,0,159,131,0,164,171,0,176,207,0,185,235,0,193,253,2,196,254,13,203,255,28,27,254,14,13,255,2,4,254,0,0,254,12,0,255,30,2,254,50,0,254,74,0,255,97,0,255,126,0,254,149,0,254,174,0,209,158,5,83,51,12,80,50,14,81,51,13,83,51,13,123,107,11,155,164,9,146,165,11,175,236,9,156,238,13,132,228,16,108,220,20,85,211,24,69,177,29,81,51,15,67,106,27,14,181,50,0,179,59,0,181,71,0,183,82,0,188,99,0,197,115,63,115,69,83,49,11,83,51,13,83,50,15,83,49,12,75,87,67,3,234,254,0,228,252,0,208,254,59,111,133,83,49,12,84,52,13,83,51,13,83,51,13,84,48,14,71,50,59,2,27,156,0,16,148,0,6,146,7,2,146,22,0,145,44,0,147,68,0,150,90,0,155,116,0,161,151,0,171,191,0,182,221,0,191,247,0,195,255,8,201,255,39,40,255,23,23,255,9,10,254,0,2,254,5,0,255,21,2,255,38,0,255,61,0,255,84,2,255,110,0,255,137,0,254,162,0,255,188,0,100,64,12,141,114,11,255,241,0,255,251,2,243,253,0,230,252,6,208,252,7,191,251,7,167,243,13,143,235,14,119,224,17,96,218,23,80,92,18,83,50,17,44,169,33,15,184,43,6,178,56,0,182,62,0,181,78,0,188,92,54,128,65,80,51,11,76,81,41,24,190,144,0,225,185,66,116,91,83,50,15,41,174,179,2,235,252,36,174,200,81,51,13,71,80,85,36,104,165,0,107,203,4,85,177,70,54,64,83,50,15,36,41,125,0,23,153,2,10,143,4,0,143,16,0,144,35,0,144,55,0,146,79,0,153,104,0,157,132,0,165,171,0,176,205,0,186,236,0,194,252,2,196,255,53,53,255,29,31,255,14,16,255,2,4,255,0,0,255,13,0,255,28,0,255,51,0,255,73,0,252,98,0,255,125,0,254,150,0,255,175,0,99,66,13,128,96,13,255,235,0,255,249,3,249,252,0,235,252,0,220,251,7,200,251,10,177,247,11,156,238,13,130,229,14,98,175,17,84,51,16,77,114,18,41,192,35,27,186,42,9,180,50,0,182,58,0,181,68,2,185,81,61,108,53,73,78,37,8,195,127,0,211,151,0,218,170,38,183,154,85,49,13,47,166,162,0,234,251,58,139,143,80,50,16,24,160,210,0,147,221,0,117,205,2,96,194,32,71,150,81,51,13,54,47,101,0,28,157,0,15,147,0,6,146,9,0,143,23,0,142,44,0,145,68,0,150,94,0,156,117,0,162,153,0,171,189,0,182,221,0,189,249,0,195,253,68,66,254,40,40,255,21,20,254,9,8,254,0,0,255,6,0,255,20,0,255,40,0,255,60,2,254,89,0,252,110,2,255,136,0,254,162,0,100,64,12,127,95,12,254,227,0,255,241,0,254,251,0,199,200,8,187,200,9,211,251,5,187,250,9,168,241,10,144,234,14,93,98,16,86,66,15,74,198,26,52,197,30,31,190,38,17,183,47,4,180,56,0,180,63,0,183,77,0,187,90,0,192,106,0,199,126,0,208,142,0,214,160,56,137,104,83,51,12,29,196,189,0,234,248,62,127,129,84,50,15,16,178,224,3,161,232,0,125,211,0,107,198,23,80,167,81,51,13,63,49,82,0,34,160,0,24,150,2,8,146,2,0,143,16,0,148,34,0,144,55,0,148,81,0,154,104,0,157,133,0,167,172,0,177,206,0,186,236,0,193,255,84,84,255,54,54,255,29,30,255,15,16,255,0,5,254,0,0,254,14,0,255,30,0,255,51,0,255,73,0,255,98,0,254,125,0,200,115,6,82,50,12,83,51,13,83,49,12,83,50,15,85,51,14,83,49,14,98,74,14,216,252,4,201,251,6,178,248,10,124,168,13,83,50,15,95,146,17,83,209,24,82,78,15,68,129,26,26,185,41,7,183,48,0,180,62,0,181,70,0,184,86,0,189,99,0,197,117,0,202,132,64,120,75,84,50,15,57,140,112,0,234,219,0,234,239,46,165,171,83,50,15,66,105,110,6,170,231,0,147,221,15,108,188,62,67,97,84,50,13,57,54,97,0,43,163,0,27,156,0,16,146,0,4,145,8,0,143,24,0,143,45,0,147,69,0,151,92,0,156,116,0,161,156,0,172,191,0,182,221,0,191,255,103,105,255,66,68,255,40,41,255,21,22,255,9,9,254,0,0,255,6,0,254,22,2,254,41,0,255,61,0,255,86,0,253,113,0,255,138,2,99,62,10,83,51,12,84,49,17,83,51,13,83,51,13,128,108,11,191,189,8,226,252,5,211,252,8,187,251,7,95,89,13,90,88,14,117,225,18,97,207,22,83,50,15,72,111,22,32,189,40,15,183,44,4,180,56,0,181,65,0,183,74,0,188,91,43,146,77,80,65,32,83,48,16,47,153,107,0,224,184,0,234,209,3,233,231,0,234,247,72,102,90,83,51,12,83,50,17,84,50,13,83,50,15,83,50,15,84,50,15,46,61,118,0,51,166,0,36,158,0,21,149,0,11,147,3,0,144,17,0,143,36,0,147,57,0,148,80,0,151,106,0,158,132,0,166,171,0,176,208,0,184,255,125,123,255,84,84,255,53,51,254,30,30,255,14,13,253,3,4,255,0,0,255,14,2,255,30,0,255,50,3,255,75,0,255,102,0,255,123,2,100,60,11,127,83,12,255,199,2,255,219,0,255,236,0,255,247,0,250,251,0,236,252,5,220,252,5,153,176,8,84,50,15,127,168,12,131,230,15,106,212,18,82,49,16,78,115,20,40,191,34,24,188,40,7,183,49,2,180,56,0,181,74,47,131,53,85,50,12,65,102,50,5,196,126,0,210,152,0,218,173,0,229,198,0,233,220,0,234,243,3,224,242,59,137,147,84,50,15,84,50,13,75,67,64,73,67,71,80,50,14,32,70,151,0,58,168,0,43,163,2,27,154,0,15,150,0,3,142,8,0,143,25,0,144,45,0,145,68,0,149,91,0,155,118,0,162,154,0,172,190,0,181,255,148,146,255,102,104,254,66,65,254,40,40,255,21,20,255,9,10,254,0,0,255,6,0,254,22,0,255,40,0,255,62,0,255,85,0,254,112,0,97,59,14,129,79,10,255,188,0,255,209,2,255,228,0,255,243,0,253,253,0,242,251,0,227,251,7,102,93,14,83,51,13,82,49,14,84,50,15,83,50,15,83,51,13,84,48,14,81,51,15,58,135,29,18,183,45,5,181,57,15,166,59,84,50,13,67,97,45,0,194,106,0,199,124,0,206,144,0,214,162,2,224,187,0,234,207,0,233,233,0,235,244,2,234,254,0,217,252,0,194,246,17,150,209,78,57,40,75,60,55,0,86,185,0,68,177,0,52,166,0,35,161,0,21,149,0,10,147,3,2,142,18,0,144,36,0,147,55,0,146,79,0,153,104,0,159,136,0,165,171,0,176,255,169,168,254,124,124,255,82,83,255,51,52,254,28,29,255,15,14,255,2,4,255,0,0,255,12,2,255,30,0,255,50,0,255,76,0,254,100,0,99,56,14,127,76,13,255,177,0,255,198,0,253,219,0,255,236,2,255,248,0,250,252,0,226,243,4,94,72,12,84,50,13,83,50,17,83,49,14,83,50,17,80,50,12,83,51,13,83,51,12,61,138,26,24,185,43,8,182,51,48,130,45,81,51,13,32,156,72,0,189,99,0,195,116,0,204,133,0,211,150,0,220,172,0,229,200,0,233,220,0,236,239,0,233,253,0,227,255,0,206,250,70,85,88,85,49,15,44,90,149,0,95,195,0,77,183,0,57,172,2,40,163,0,29,150,0,14,149,0,5,145,9,0,143,27,0,144,45,0,145,69,0,150,92,0,156,121,0,162,152,0,170,253,192,191,253,147,147,255,102,102,255,65,65,255,40,38,255,21,20,255,8,9,254,0,0,252,8,0,255,21,0,255,40,0,255,61,0,253,87,0,99,56,13,130,71,11,254,165,0,255,188,0,255,209,2,255,228,0,253,245,0,253,252,2,243,252,3,230,252,4,210,252,4,188,249,5,166,242,12,140,224,14,84,50,12,88,119,16,72,204,32,51,196,29,31,188,37,13,184,46,62,104,32,80,51,11,83,49,12,85,51,14,83,50,17,85,49,13,83,49,14,79,66,34,7,215,179,0,235,205,0,234,231,0,232,249,6,225,244,68,109,113,82,50,12,56,103,129,0,125,211,0,107,197,0,86,187,0,68,179,0,50,165,0,34,157,0,20,151,0,10,146,4,0,142,17,0,143,35,0,146,58,0,147,80,0,154,106,0,158,135,0,165,255,211,210,254,168,167,255,122,123,255,82,83,255,51,50,254,28,29,255,15,14,254,2,0,255,0,0,255,13,0,252,32,0,255,54,0,255,74,0,127,61,9,154,80,7,255,151,4,255,176,0,255,198,0,255,219,0,255,234,0,255,250,2,250,250,4,232,252,5,217,253,7,199,253,9,173,247,10,150,229,13,84,50,13,91,122,18,84,208,22,60,200,29,41,192,35,26,185,41,59,114,31,83,50,17,85,51,14,82,49,14,81,51,15,83,49,12,81,52,12,48,151,104,0,219,175,0,228,200,0,234,220,35,188,186,80,69,47,83,51,13,63,115,126,0,177,237,0,143,222,0,114,206,2,96,194,2,77,179,0,57,170,0,42,162,0,28,154,0,16,148,0,4,143,9,0,143,25,0,144,48,0,148,67,0,151,94,0,156,121,0,163,255,228,230,255,191,191,255,144,146,254,101,103,253,65,64,252,38,38,254,20,21,253,8,7,254,0,0,255,8,0,255,23,0,255,39,0,255,64,0,255,85,0,255,111,2,255,140,0,255,164,0,255,188,0,255,210,3,254,229,2,253,242,0,255,252,0,243,253,0,226,252,5,207,252,3,190,251,10,165,242,14,91,87,16,99,149,16,95,215,22,73,204,26,50,196,33,31,189,40,15,183,48,2,180,56,0,179,62,0,184,80,0,186,92,0,194,108,0,198,126,0,206,142,0,215,160,0,225,187,2,234,210,59,129,118,79,72,44,48,163,170,0,216,255,0,192,246,0,160,230,0,126,211,0,106,197,0,83,185,3,67,175,0,50,165,0,34,158,0,21,149,0,9,146,3,0,144,17,0,143,37,0,146,56,0,149,81,0,154,106,0,158,254,244,243,255,212,211,255,167,166,255,122,123,255,83,83,255,50,50,255,28,29,255,13,13,255,2,4,255,2,0,255,13,0,255,32,0,255,52,2,252,77,0,253,102,0,255,126,0,255,151,0,253,178,0,254,201,0,255,221,0,254,237,0,254,249,0,250,250,2,234,253,5,220,251,7,195,253,8,178,244,10,154,239,14,130,229,16,106,220,21,80,210,24,60,200,29,39,193,35,24,185,43,8,182,51,0,181,62,0,180,71,0,186,83,0,191,98,0,197,118,0,205,133,0,210,152,0,220,174,0,230,199,0,232,222,0,233,238,0,235,252,0,228,255,0,205,252,0,177,239,0,142,218,2,113,205,0,97,191,0,77,183,0,59,173,0,42,160,0,26,153,0,14,149,0,5,145,10,0,144,29,0,145,46,0,146,70,0,150,94,0,156};
4 |
--------------------------------------------------------------------------------