Professional Documents
Culture Documents
Le Trong Nhan
Mục lục
Chapter 1. Buttons/Switches 7
1 Objectives . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
2 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
3 Basic techniques for reading from port pins . . . . . . . . . . . . . . . 10
3.1 The need for pull-up resistors . . . . . . . . . . . . . . . . . . . . 10
3.2 Dealing with switch bounces . . . . . . . . . . . . . . . . . . . . 10
4 Reading switch input (basic code) using STM32 . . . . . . . . . . . . . 15
4.1 Input Output Processing Patterns . . . . . . . . . . . . . . . . . 15
4.2 Setting up . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
4.2.1 Create a project . . . . . . . . . . . . . . . . . . . . . . . 16
4.2.2 Create a file C source file and header file for input
reading . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
4.3 Code For Read Port Pin and Debouncing . . . . . . . . . . . . . 18
4.3.1 The code in the input_reading.c file . . . . . . . . . . 18
4.3.2 The code in the input_reading.h file . . . . . . . . . . 19
4.3.3 The code in the timer.c file . . . . . . . . . . . . . . . . 19
4.4 Button State Processing . . . . . . . . . . . . . . . . . . . . . . . 20
4.4.1 Finite State Machine . . . . . . . . . . . . . . . . . . . . 20
4.4.2 The code for the FSM in the input_processing.c file 21
4.4.3 The code in the input_processing.h . . . . . . . . . . 21
4.4.4 The code in the main.c file . . . . . . . . . . . . . . . . 22
5 Exercises and Report . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
5.1 Specifications . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
5.2 Exercise 1: Sketch an FSM . . . . . . . . . . . . . . . . . . . . . . 24
5.3 Exercise 2: Proteus Schematic . . . . . . . . . . . . . . . . . . . . 25
5.4 Exercise 3: Create STM32 Project . . . . . . . . . . . . . . . . . . 25
Microcontroller Page 5
5.5 Exercise 4: Modify Timer Parameters . . . . . . . . . . . . . . . 27
5.6 Exercise 5: Adding code for button debouncing . . . . . . . . . 27
5.6.1 The code in the input_reading.h file . . . . . . . . . . 27
5.6.2 The code for button debouncing and reading but-
ton in the input_reading.c file . . . . . . . . . . . . . . 28
5.6.3 Code for change mode when press first button in
the ouptut_processing.c file . . . . . . . . . . . . . . . 29
5.7 Exercise 6: Adding code for displaying modes . . . . . . . . . . 32
5.7.1 Code for display mode on 7-SEG in led_display.h file 32
5.7.2 Code for display mode on 7-SEG in led_display.c file 32
5.7.3 The code for display 7SEG and led blinky in the out-
put_processing.c file . . . . . . . . . . . . . . . . . . . . 34
5.7.4 The code for traffic led in traffic_led.c file . . . . . . . 37
5.8 Exercise 7: Adding code for increasing time duration value for
the red LEDs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
5.9 Exercise 8: Adding code for increasing time duration value for
the amber LEDs . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
5.10 Exercise 9: Adding code for increasing time duration value for
the green LEDs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
5.11 Exercise 10: To finish the project . . . . . . . . . . . . . . . . . . 44
Microcontroller Page 6
CHƯƠNG 1
Buttons/Switches
1 Objectives
• Learn how to add new C source files and C header files in an STM32 project,
• Learn how to read digital inputs and display values to LEDs using a timer
interrupt of a microcontroller (MCU).
• Learn how to debounce when reading a button.
2 Introduction
Embedded systems usually use buttons (or keys, or switches, or any form of me-
chanical contacts) as part of their user interface. This general rule applies from the
most basic remote-control system for opening a garage door, right up to the most
sophisticated aircraft autopilot system. Whatever the system you create, you need
to be able to create a reliable button interface.
A button is generally hooked up to an MCU so as to generate a certain logic level
when pushed or closed or “active" and the opposite logic level when unpushed or
open or “inactive." The active logic level can be either ‘0’ or ‘1’, but for reasons both
historical and electrical, an active level of ’0’ is more common.
We can use a button if we want to perform operations such as:
Microcontroller Page 8
In this lab, we consider how you read inputs from mechanical buttons in your em-
bedded application using an MCU.
Microcontroller Page 9
3 Basic techniques for reading from port pins
Figure 1.1 shows a way to connect a button to an MCU. This hardware operates as
follows:
• When the switch is open, it has no impact on the port pin. An internal resistor
on the port “pulls up" the pin to the supply voltage of the MCU (typically 3.3V
for STM32F103). If we read the pin, we will see the value ‘1’.
• When the switch is closed (pressed), the pin voltage will be 0V. If we read the
pin, we will see the value ‘0’.
However, if the MCU does not have a pull-up resistor inside, when the button is
pressed, the read value will be ‘0’, but even we release the button, the read value is
still ‘0’ as shown in Figure 1.2.
So a reliable way to connect a button/switch to an MCU is that we explicitly use an
external pull-up resistor as shown in Figure 1.3.
In practice, all mechanical switch contacts bounce (that is, turn on and off, re-
peatedly, for short period of time) after the switch is closed or opened as shown in
Figure 1.4.
Every system that uses any kind of mechanical switch must deal with the issue of
debouncing. The key task is to make sure that one mechanical switch or button
action is only read as one action by the MCU, even though the MCU will typically
be fast enough to detect the unwanted switch bounces and treat them as separate
events. Bouncing can be eliminated by special ICs or by RC circuitry, but in most
cases debouncing is done in software because software is “free".
As far as the MCU concerns, each “bounce" is equivalent to one press and release
of an “ideal” switch. Without appropriate software design, this can give several
problems:
Microcontroller Page 10
Hình 1.2: The need of pull up resistors
Microcontroller Page 11
• Rather than reading ‘A’ from a keypad, we may read ‘AAAAA’
• If a switch is depressed once, and then released some time later, the ‘bounce’
may make it appear as if the switch has been pressed again (at the time of
release).
The key to debouncing is to establish a minimum criterion for a valid button push,
one that can be implemented in software. This criterion must involve differences
in time - two button presses in 20ms must be treated as one button event, while
two button presses in 2 seconds must be treated as two button events. So what are
the relevant times we need to consider? They are these:
• Button press time: the shortest time a user can press and release a button
seems to be between 50 and 100ms
• Response time: a user notices if the system response is 100ms after the button
press, but not if it is 50ms after
The simplest debouncing method is to examine the keys (or buttons or switches)
every N milliseconds, where N > 10ms (our specified button bounce upper limit)
and N <= 50ms (our specified response time). We then have three possible out-
comes every time we read a button:
• We read the button while it is bouncing (so we will get either a ‘0’ or a ‘1’)
Outcomes 1 and 2 pose no problems, as they are what we would always like to
happen. Outcome 3 also poses no problem because during a bounce either state
is acceptable. If we have just pressed an active-low button and we read a ’1’ as it
bounces, the next time through we are guaranteed to read a ’0’ (remember, the
next time through all bouncing will have ceased), so we will just detect the button
push a bit later. Otherwise, if we read a ’0’ as the button bounces, it will still be ’0’
the next time after all bouncing has stopped, so we are just detecting the button
push a bit earlier. The same applies to releasing a button. Reading a single bounce
(with all bouncing over by the time of the next read) will never give us an invalid
button state. It’s only reading multiple bounces (multiple reads while bouncing is
Microcontroller Page 12
occurring) that can give invalid button states such as repeated push signals from
one physical push.
So if we guarantee that all bouncing is done by the time we next read the button,
we’re good. Well, almost good, if we’re lucky...
MCUs often live among high-energy beasts, and often control the beasts. High en-
ergy devices make electrical noise, sometimes great amounts of electrical noise.
This noise can, at the worst possible moment, get into your delicate button-and-
high-value-pullup circuit and act like a real button push. Oops, missile launched,
sorry!
If the noise is too intense we cannot filter it out using only software, but will need
hardware of some sort (or even a redesign). But if the noise is only occasional,
we can filter it out in software without too much bother. The trick is that instead
of regarding a single button ‘make’ or ‘break’ as valid, we insist on N contiguous
makes or breaks to mark a valid button event. N will be a factor of your button
scanning rate and the amount of filtering you want to add. Bigger N gives more
filtering. The simplest filter (but still a big improvement over no filtering) is just an
N of 2, which means compare the current button state with the last button state,
and only if both are the same is the output valid.
Note that now we have not two but three button states: active (or pressed), inac-
tive (or released), and indeterminate or invalid (in the middle of filtering, not yet
filtered). In most cases we can treat the invalid state the same as the inactive state,
since we care in most cases only about when we go active (from whatever state)
and when we cease being active (to inactive or invalid). With that simplification
we can look at simple N = 2 filtering reading a button wired to STM32 MCU:
1 void button_reading ( void ) {
2 static unsigned char last_button ;
3 unsigned char raw_button ;
4 unsigned char filtered_button ;
5 last_button = raw_button ;
6 raw_button = HAL_GPIO_ReadPin ( BUTTON_1_GPIO_Port ,
BUTTON_1_Pin ) ;
7 if ( last_button == raw_button ) {
8 filtered_button = raw_button ;
9 }
10 }
Program 1.1: Read port pin and deboucing
The function button_reading() must be called no more often than our debounce
time (10ms).
To expand to greater filtering (larger N), keep in mind that the filtering technique
essentially involves reading the current button state and then either counting or
reseting the counter. We count if the current button state is the same as the last
button state, and if our count reaches N we then report a valid new button state.
We reset the counter if the current button state is different than the last button
state, and we then save the current button state as the new button state to com-
pare against the next time. Also note that the larger our value of N the more often
our filtering routine must be called, so that we get a filtered response within our
Microcontroller Page 13
specified 50ms deadline. So for example with an N of 8 we should be calling our
filtering routine every 2 - 5ms, giving a response time of 16 - 40ms (>10ms and
<50ms).
Microcontroller Page 14
4 Reading switch input (basic code) using STM32
• Increases the value of LEDs connected to PORTA by one unit when the button
PB0 is pressed.
• Increases the value of PORTA automatically in every 0.5 second, if the button
PB0 is pressed in more than 1 second.
For both input and output processing, we have a similar pattern to work with. Nor-
mally, we have a module named driver which works directly to the hardware. We
also have a buffer to store temporarily values. In the case of input processing, the
driver will store the value of the hardware status to the buffer for further process-
ing. In the case of output processing, the driver uses the buffer data to output to
the hardware.
Figure 1.5 shows that we should have an input_reading module to processing the
buttons, then store the processed data to the buffer. Then a module of input_output_processin
will process the input data, and update the output buffer. The output driver gets
the value from the output buffer to transfer to the hardware.
Microcontroller Page 15
4.2 Setting up
Please follow the instruction in Labs 1 and 2 to create a project that includes:
4.2.2 Create a file C source file and header file for input reading
We are expected to have files for button processing and led display as shown in
Figure 1.6.
Steps 1 (Figure 1.7): Right click to the folder Src, select New, then select Source
File. There will be a pop-up. Please type the file name, then click Finish.
Step 2 (Figure 1.8): Do the same for the C header file in the folder Inc.
Microcontroller Page 16
Hình 1.7 : Step 1: Create a C source file for input reading
Microcontroller Page 17
4.3 Code For Read Port Pin and Debouncing
Microcontroller Page 18
1 unsigned char is_button_pressed ( uint8_t index ) {
2 if ( index >= N0_OF_BUTTONS ) return 0;
3 return ( buttonBuffer [ index ] == BUTTON_IS_PRESSED ) ;
4 }
Program 1.3: Checking a button is pressed or not
1 # ifndef INC_INPUT_READING_H_
2 # define INC_INPUT_READING_H_
3 void button_reading ( void ) ;
4 unsigned char is_button_pressed ( unsigned char index ) ;
5 unsigned char is_button_pressed_1s ( unsigned char index ) ;
6 # endif /* INC_INPUT_READING_H_ */
Program 1.5: Prototype in input_reading.h file
Microcontroller Page 19
4.4 Button State Processing
• State 1: When the button is pressed, the FSM will change to State 1 that is
increasing the values of PORTA by one value. If the button is released, the
FSM goes back to State 0.
• State 2: while the FSM is in State 1, the button is kept pressing more than 1
second, the state of FSM will change from 1 to 2. In this state, if the button
is kept pressing, the value of PORTA will be increased automatically in every
500ms. If the button is released, the FSM goes back to State 0.
Microcontroller Page 20
4.4.2 The code for the FSM in the input_processing.c file
Please note that fsm_for_input_processing function should be called inside the su-
per loop of the main functin.
1 # include " main . h "
2 # include " input_reading . h "
3
1 # ifndef INC_INPUT_PROCESSING_H_
2 # define INC_INPUT_PROCESSING_H_
3
6 # endif /* INC_INPUT_PROCESSING_H_ */
Program 1.8: Code in the input_processing.h file
Microcontroller Page 21
4.4.4 The code in the main.c file
Microcontroller Page 22
5 Exercises and Report
5.1 Specifications
You are required to build an application of a traffic light in a cross road which in-
cludes some features as described below:
• The application has 12 LEDs including 4 red LEDs, 4 amber LEDs, 4 green
LEDs.
• The application has 4 seven segment LEDs to display time with 2 for each
road. The 2 seven segment LEDs will show time for each color LED corre-
sponding to each road.
• The application has at least 4 modes which is controlled by the first button.
Mode 1 is a normal mode, while modes 2 3 4 are modification modes. You
can press the first button to change the mode. Modes will change from 1 to 4
and back to 1 again.
Mode 1 - Normal mode:
- The traffic light application is running normally.
Mode 2 - Modify time duration for the red LEDs: This mode allows you to
change the time duration of the red LED in the main road. The expected be-
haviours of this mode include:
- All single red LEDs are blinking in 2 Hz.
- Use two seven-segment LEDs to display the value.
- Use the other two seven-segment LEDs to display the mode.
- The second button is used to increase the time duration value for the
red LEDs.
- The value of time duration is in a range of 1 - 99.
- The third button is used to set the value.
Mode 3 - Modify time duration for the amber LEDs: Similar for the red LEDs
described above with the amber LEDs.
Mode 4 - Modify time duration for the green LEDs: Similar for the red LEDs
described above with the green LEDs.
Microcontroller Page 23
5.2 Exercise 1: Sketch an FSM
Your task in this exercise is to sketch an FSM that describes your idea of how to
solve the problem.
Microcontroller Page 24
5.3 Exercise 2: Proteus Schematic
Your task in this exercise is to draw a Proteus schematic for the problem above.
Your task in this exercise is to create a project that has pin corresponding to the
Proteus schematic that you draw in previous section. You need to set up your timer
interrupt is about 10ms.
Please add your report here.
Microcontroller Page 25
Hình 1.11: Cài đặt timer_interupt là 10ms
Microcontroller Page 26
5.5 Exercise 4: Modify Timer Parameters
Your task in this exercise is to modify the timer settings so that when we want
to change the time duration of the timer interrupt, we change it the least and it
will not affect the overall system. For example, the current system we have imple-
mented is that it can blink an LED in 2 Hz, with the timer interrupt duration is
10ms. However, when we want to change the timer interrupt duration to 1ms or
100ms, it will not affect the 2Hz blinking LED.
Please add your report here.
1 # define TIMER_CYCLE 10;
Program 1.10: define TIMER_CYCLE in software_timer.h
Giá trị TIMER_CYCLE được gán bằng timer interrupt của TIM2 là 10(ms). Trong
trường hợp nếu có thay đổi giá trị interupt thay đổi thì chỉ cần thay đổi giá trị của
TIMER_CYCLE.
Following the example of button reading and debouncing in the previous section,
your tasks in this exercise are:
• To add code for increasing mode when the first button is pressed.
1 # ifndef INC_INPUT_READING_H_
2 # define INC_INPUT_READING_H_
3
8 # endif /* INC_INPUT_READING_H_ */
Program 1.12: Khai báo prototype trong file input_reading.h
Microcontroller Page 27
• Hàm button_reading_Init được gọi trước khi vào hàm main để set các button
ở trạng thái RELEASED.
• Hàm button_reading để đọc trạng thái của nút nhấn và gán vào buttonBuffer
để sử dụng cho máy trạng thái.
• Hàm is_button_pressed để kiểm tra xem nút nhấn tại vị trí index có được
nhấn hay không.
5.6.2 The code for button debouncing and reading button in the input_reading.c
file
Microcontroller Page 28
34 }
35 }
36
1 while (1)
2 {
3 fsm_for_output_processing () ;
4 }
Program 1.15: Máy trạng thái được gọi trong while(1)
Máy trạng thái sẽ liên tục được gọi trong while(1). Còn giá trị của nút nhấn sẽ được
cập nhật mỗi 10ms khi hàm ngắt được gọi.
5.6.3 Code for change mode when press first button in the ouptut_processing.c
file
Microcontroller Page 29
17 buttonflag0 = 1; // update buttonflag0 to avoid
change mode randomly
18 Mode = MODE_2 ;
19 counter_mode2 = 0;
20 LED_TRAFFIC_INIT () ;
21 setTimer (1000) ;
22 }
23 } else {
24 buttonflag0 = 0; // update buttonflag0 when
button0 is realeased
25 }
26 // SET_TIMER 1 S IF DON ’T PRESS
27 if ( timer0_flag == 1) {
28 setTimer (1000) ;
29 }
30 break ;
31 case MODE_2 :
32 // BUTTON_0 PRESS
33 if ( is_button_pressed (0) ) {
34 if ( buttonflag0 == 0) {
35 buttonflag0 = 1; // update buttonflag0 to avoid
change mode randomly
36 Mode = MODE_3 ;
37 counter_mode3 = 0;
38 LED_TRAFFIC_INIT () ;
39 setTimer (1000) ;
40 }
41 } else {
42 buttonflag0 = 0; // update buttonflag0 when button0
is realeased
43 }
44 // SET_TIMER 1 S IF DON ’T PRESS
45 if ( timer0_flag == 1) {
46 setTimer (1000) ;
47 }
48 break ;
49 case MODE_3 :
50 // BUTTON_0 PRESS
51 if ( is_button_pressed (0) ) {
52 if ( buttonflag0 == 0) {
53 buttonflag0 = 1; // update buttonflag0 to avoid
change mode randomly
54 Mode = MODE_4 ;
55 counter_mode4 = 0;
56 LED_TRAFFIC_INIT () ;
57 setTimer (1000) ;
58 }
59 } else {
60 buttonflag0 = 0; // update buttonflag0 when button0
Microcontroller Page 30
is realeased
61 }
62 // SET_TIMER 1 S IF DON ’T PRESS
63 if ( timer0_flag == 1) {
64 setTimer (1000) ;
65 }
66 break ;
67 case MODE_4 :
68 // BUTTON_0 PRESS
69 if ( is_button_pressed (0) ) {
70 if ( buttonflag0 == 0) {
71 buttonflag0 = 1; // update buttonflag0 to avoid
change mode randomly
72 Mode = MODE_1 ;
73 LED_TRAFFIC_LOAD_BUFFER () ;
74 LED_TRAFFIC_INIT () ;
75 setTimer (1000) ;
76 }
77 } else {
78 buttonflag0 = 0; // update buttonflag0 when button0
is realeased
79 }
80 // SET_TIMER 1 S IF DON ’T PRESS
81 if ( timer0_flag == 1) {
82 setTimer (1000) ;
83 }
84 break ;
85 default :
86 Mode = MODE_1 ;
87 }
88 }
Program 1.16: Code for change mode in the output_processing.c file
• Với câu lệnh gán enum MODE Mode = MODE_1 thì mặc định Mode sẽ là
MODE_1 khi máy trạng thái được gọi lần đầu.
• Cờ buttonflag0 được dùng để tránh trường hợp mode bị nhảy cóc sai ý muốn
mỗi khi người dùng nhấn nút. Qui ước khi buttonflag0 bằng 0 thì khi nhấn
mới có tác dụng và ngay sao đó sẽ set buttonflag0 lên 1. Chỉ khi nào người
dùng nhả nút nhấn ra thì cờ mới được cập nhật về 0 cho lần nhấn kế tiếp. Ở
đây chưa xét trường hợp nhấn đè.
• Khi nhấn button_0 hệ thống sẽ kiểm tra xem cờ của nút nhấn đã sẽ chuyển
qua Mode kế tiếp đồng thời set thời gian cho trạng thái kế tiếp là 1s. Ngoài
ra khi chuyển trạng thái thì các đèn sẽ được khởi động lại thông qua hàm
LED_TRAFFIC_INIT được khai báo và sử dụng trọng file led_traffic.c.
Microcontroller Page 31
5.7 Exercise 6: Adding code for displaying modes
• To add code for blinking LEDs depending on the mode that is selected.
1 # ifndef INC_LED_DISPLAY_H_
2 # define INC_LED_DISPLAY_H_
3
11 # endif /* INC_LED_DISPLAY_H_ */
Program 1.17: Khai báo prototype trong file led_display.h
• Hàm update_all_clock_buffer: dùng để cập nhật lại buffer khi thay đổi thời
gian ở các mode khi nhấn Button_3
• Hàm update_7SEG_driver: dùng để quét từng LED trước khi hiển thị
• Hàm displayLED7: dùng để set các chân LED7 hiển thị ra màn hình
4 # define NUMBER_OF_7_SEG_LED 4
5
Microcontroller Page 32
8 0 x06 , // 1
9 0 x5b , // 2
10 0 x4f , // 3
11 0 x66 , // 4
12 0 x6d , // 5
13 0 x7d , // 6
14 0 x07 , // 7
15 0 x7f , // 8
16 0 x67 // 9
17 };
18
Microcontroller Page 33
56 switch ( index ) {
57 case 0:
58 buffer [0]= LED7Conversion [ numBuffer [0]];
59 displayLED7 (0) ;
60 HAL_GPIO_WritePin ( EN0_GPIO_Port , EN0_Pin ,0) ;
61 break ;
62 case 1:
63 buffer [1]= LED7Conversion [ numBuffer [1]];
64 displayLED7 (1) ;
65 HAL_GPIO_WritePin ( EN1_GPIO_Port , EN1_Pin ,0) ;
66 break ;
67 case 2:
68 buffer [2]= LED7Conversion [ numBuffer [2]];
69 displayLED7 (2) ;
70 HAL_GPIO_WritePin ( EN2_GPIO_Port , EN2_Pin ,0) ;
71 break ;
72 case 3:
73 buffer [3]= LED7Conversion [ numBuffer [3]];
74 displayLED7 (3) ;
75 HAL_GPIO_WritePin ( EN3_GPIO_Port , EN3_Pin ,0) ;
76 break ;
77 }
78 }
79
80 // Display LED7
81 void displayLED7 ( uint8_t index ) {
82 HAL_GPIO_WritePin ( SEG_A_GPIO_Port , SEG_A_Pin , !(( buffer [
index ] > >0) &0 x01 ) ) ;
83 HAL_GPIO_WritePin ( SEG_B_GPIO_Port , SEG_B_Pin , !(( buffer [
index ] > >1) &0 x01 ) ) ;
84 HAL_GPIO_WritePin ( SEG_C_GPIO_Port , SEG_C_Pin , !(( buffer [
index ] > >2) &0 x01 ) ) ;
85 HAL_GPIO_WritePin ( SEG_D_GPIO_Port , SEG_D_Pin , !(( buffer [
index ] > >3) &0 x01 ) ) ;
86 HAL_GPIO_WritePin ( SEG_E_GPIO_Port , SEG_E_Pin , !(( buffer [
index ] > >4) &0 x01 ) ) ;
87 HAL_GPIO_WritePin ( SEG_F_GPIO_Port , SEG_F_Pin , !(( buffer [
index ] > >5) &0 x01 ) ) ;
88 HAL_GPIO_WritePin ( SEG_G_GPIO_Port , SEG_G_Pin , !(( buffer [
index ] > >6) &0 x01 ) ) ;
89 }
Program 1.18: Hiện thực hàm trong file led_display.c
5.7.3 The code for display 7SEG and led blinky in the output_processing.c file
Microcontroller Page 34
3
Microcontroller Page 35
50 setBlinkLedTimer (250) ;
51 }
52 break ;
53 case MODE_3 :
54 // UPDATE AND DISPLAY LED7
55 update_all_clock_buffer ( counter_mode3 , 3) ;
56 if ( led_7_flag ) {
57 update_LED7_driver ( index_led7 ) ;
58 index_led7 ++;
59 if ( index_led7 == 4) index_led7 = 0;
60 setLED7Timer (250) ;
61 }
62 // BLINK ALL LED AMBER 2 HZ
63 if ( blink_flag ) {
64 HAL_GPIO_TogglePin ( LED_AMBER1_GPIO_Port ,
LED_AMBER1_Pin ) ;
65 HAL_GPIO_TogglePin ( LED_AMBER2_GPIO_Port ,
LED_AMBER2_Pin ) ;
66 setBlinkLedTimer (250) ;
67 }
68 break ;
69 case MODE_4 :
70 // UPDATE AND DISPLAY LED7
71 update_all_clock_buffer ( counter_mode4 , 4) ;
72 if ( led_7_flag ) {
73 update_LED7_driver ( index_led7 ) ;
74 index_led7 ++;
75 if ( index_led7 == 4) index_led7 = 0;
76 setLED7Timer (250) ;
77 }
78 // BLINK ALL LED GREEN 2 HZ
79 if ( blink_flag ) {
80 HAL_GPIO_TogglePin ( LED_GREEN1_GPIO_Port ,
LED_GREEN1_Pin ) ;
81 HAL_GPIO_TogglePin ( LED_GREEN2_GPIO_Port ,
LED_GREEN2_Pin ) ;
82 setBlinkLedTimer (250) ;
83 }
84 break ;
85 default :
86 Mode = MODE_1 ;
87 }
88 }
Program 1.19: The code for display 7SEG and led blinky in output_processing.c file
• Ban đầu các tên đèn sẽ được định nghĩa lại bởi các con số tương ứng RED(2),
AMBER(3), GREEN(4) và các biến counter_mode2, counter_mode3, counter_mode4
sẽ đại diện cho thời gian của từng loại đèn để thuận tiện cho quá trình điều
chỉnh.
Microcontroller Page 36
• Khi ở MODE_1 hệ thống sẽ hiển thị trên các led 7 đoạn mặc định Đỏ (5s),
Amber (2s), Green (3s). Giá trị khởi tạo này được load vào buffer trong hàm
main trước khi vòng while được gọi. Và khi cờ led_7_flag bằng 1 thì sẽ dùng
phương pháp quét led để hiện thị các số lên LED7.
• Khi ở MODE_2 việc đầu tiên chúng ta cần làm là update lại giá trị counter cho
đèn đỏ. Trong quá trình update hệ thống sẽ hiển thị counter lên LED7, đồng
thời các led đỏ đơn sẽ liên tục nhấp nháy với tần số 2HZ khi cờ blink_flag lên
1.
• Tương tự đối với MODE_3 và MODE_4 ứng với LED AMBER và LED GREEN.
5 # define N0_OF_LED 3
6
7 # define RED 0
8 # define AMBER 1
9 # define GREEN 2
10
Microcontroller Page 37
30 // Function to load value are saved in buffer to counter
and time of each led
31 // to use for display in 7 SEG
32 void LED_TRAFFIC_LOAD_BUFFER ( void ) {
33 counterRED1 = bufferTimerForLED [ RED ];
34 counterAMBER1 = bufferTimerForLED [ AMBER ];
35 counterGREEN1 = bufferTimerForLED [ GREEN ];
36 counterRED2 = bufferTimerForLED [ RED ];
37 counterAMBER2 = bufferTimerForLED [ AMBER ];
38 counterGREEN2 = bufferTimerForLED [ GREEN ];
39 timeRED = bufferTimerForLED [ RED ];
40 timeAMBER = bufferTimerForLED [ AMBER ];
41 timeGREEN = bufferTimerForLED [ GREEN ];
42 }
43
59 }
60 // AMBER1 - ON
61 else if ( counterAMBER2 > 0) {
62 update_vertical_clock_buffer ( counterAMBER2 ) ;
63 HAL_GPIO_WritePin ( LED_RED1_GPIO_Port , LED_RED1_Pin , SET
);
64 HAL_GPIO_WritePin ( LED_AMBER1_GPIO_Port , LED_AMBER1_Pin ,
RESET ) ;
65 HAL_GPIO_WritePin ( LED_GREEN1_GPIO_Port , LED_GREEN1_Pin ,
SET ) ;
66 counterAMBER2 - -;
67 }
68 // RED1 - ON
69 else if ( counterRED2 > 0) {
70 update_vertical_clock_buffer ( counterRED2 ) ;
71 HAL_GPIO_WritePin ( LED_RED1_GPIO_Port , LED_RED1_Pin ,
Microcontroller Page 38
RESET ) ;
72 HAL_GPIO_WritePin ( LED_AMBER1_GPIO_Port , LED_AMBER1_Pin ,
SET ) ;
73 HAL_GPIO_WritePin ( LED_GREEN1_GPIO_Port , LED_GREEN1_Pin ,
SET ) ;
74 counterRED2 - -;
75 }
76 if ( counterRED2 == 0) {
77 counterRED2 = timeRED ;
78 counterAMBER2 = timeAMBER ;
79 counterGREEN2 = timeGREEN ;
80 }
81 }
82
Microcontroller Page 39
109 if ( counterGREEN1 == 0) {
110 counterRED1 = timeRED ;
111 counterAMBER1 = timeAMBER ;
112 counterGREEN1 = timeGREEN ;
113 }
114 }
115
5.8 Exercise 7: Adding code for increasing time duration value for
the red LEDs
• to use the second button to increase the time duration value of the red LEDs
• to use the third button to set the value for the red LEDs.
Microcontroller Page 40
12 void fsm_for_output_processing ( void ) {
13 switch ( Mode ) {
14 case MODE_1 :
15 // UPADTE AND DISPLAY LED7
16 if ( led_7_flag ) {
17 update_LED7_driver ( index_led7 ) ;
18 index_led7 ++;
19 if ( index_led7 == 4) index_led7 = 0;
20 setLED7Timer (250) ;
21 }
22 // BUTTON_0 PRESS
23 if ( is_button_pressed (0) == 1) {
24 if ( buttonflag0 == 0) {
25 buttonflag0 = 1; // update buttonflag0 to avoid
change mode randomly
26 Mode = MODE_2 ;
27 counter_mode2 = 0;
28 LED_TRAFFIC_INIT () ;
29 setTimer (1000) ;
30 }
31 } else {
32 buttonflag0 = 0; // update buttonflag0 when
button0 is realeased
33 }
34 // SET_TIMER 1 S IF DONT PRESS AND INIT LED_TRAFFIC
35 if ( timer0_flag == 1) {
36 if ( init == 0) {
37 LED_TRAFFIC_INIT () ;
38 init = 1;
39 }
40 LED_TRAFFIC_RUN () ;
41 setTimer (1000) ;
42 }
43 break ;
44 case MODE_2 :
45 // BUTTON_1 PRESS
46 if ( is_button_pressed (1) ) {
47 if ( buttonflag1 == 0) {
48 buttonflag1 = 1; // update buttonflag1 to avoid
change mode randomly
49 counter_mode2 = ( counter_mode2 + 1) % 99;
50 }
51 } else buttonflag1 = 0; // update buttonflag1 when
button1 is realeased
52 // BUTTON_2 PRESS
53 if ( is_button_pressed (2) ) {
54 if ( buttonflag2 == 0) {
55 buttonflag2 = 1; // update buttonflag2 to avoid
change mode randomly
Microcontroller Page 41
56 LED_TRAFFIC_STORE_BUFFER ( counter_mode2 , RED ) ;
57 }
58 } else {
59 buttonflag2 = 0; // update buttonflag2 when button2
is realeased
60 }
61 // SET_TIMER 1 S IF DONT PRESS
62 if ( timer0_flag == 1) {
63 setTimer (1000) ;
64 }
65 break ;
66 default :
67 Mode = MODE_1 ;
68 }
69 }
Program 1.21: Code for second and third button in ouput_processing.c with red
led
• Ở bài tập này chúng ta sử dụng các cở button1flag và button2flag có tác dụng
tương tự như button0flag ở câu trên.
• Khi trạng thái ở MODE_1 thì chúng ta sẽ không xét đến trường hợp nhấn
button1 hoặc button2
• Khi ở các Mode còn lại mỗi khi button1 được nhấn thì giá trị counter sẽ tăng
lên như yêu cầu của đề bài. Khi button2 được nhấn thì hàm LED_TRAFFIC_-
STORE_BUFFER được sử dụng để cập nhật lại counter cho led tương ứng ở
Mode đó.
5.9 Exercise 8: Adding code for increasing time duration value for
the amber LEDs
• to use the second button to increase the time duration value of the amber
LEDs
• to use the third button to set the value for the amber LEDs.
Microcontroller Page 42
8 buttonflag1 = 1; // update buttonflag1 to avoid
change mode randomly
9 counter_mode3 = ( counter_mode3 + 1) % 99;
10 }
11 } else {
12 buttonflag1 = 0; // update buttonflag1 when button1
is realeased
13 }
14 // BUTTON_2 PRESS
15 if ( is_button_pressed (2) ) {
16 if ( buttonflag2 == 0) {
17 buttonflag2 = 1; // update buttonflag2 to avoid
change mode randomly
18 LED_TRAFFIC_STORE_BUFFER ( counter_mode3 , AMBER ) ;
19 }
20 } else {
21 buttonflag2 = 0; // update buttonflag2 when button2
is realeased
22 }
23 // SET_TIMER 1 S IF DONT PRESS
24 if ( timer0_flag == 1) {
25 setTimer (1000) ;
26 }
27 break ;
28 default :
29 Mode = MODE_1 ;
30 }
31 }
Program 1.22: Code for second and third button in ouput_processing.c with amber
led
• to use the second button to increase the time duration value of the green
LEDs
• to use the third button to set the value for the green LEDs.
Microcontroller Page 43
5 // BUTTON_1 PRESS
6 if ( is_button_pressed (1) ) {
7 if ( buttonflag1 == 0) {
8 buttonflag1 = 1; // update buttonflag1 to avoid
change mode randomly
9 counter_mode4 = ( counter_mode4 + 1) % 99;
10 }
11 } else {
12 buttonflag1 = 0; // update buttonflag1 when button1
is realeased
13 }
14 // BUTTON_2 PRESS
15 if ( is_button_pressed (2) ) {
16 if ( buttonflag2 == 0) {
17 buttonflag2 = 1; // update buttonflag2 to avoid
change mode randomly
18 LED_TRAFFIC_STORE_BUFFER ( counter_mode4 , GREEN ) ;
19 }
20 } else {
21 buttonflag2 = 0; // update buttonflag2 when button2
is realeased
22 }
23 // SET_TIMER 1 S IF DONT PRESS
24 if ( timer0_flag == 1) {
25 setTimer (1000) ;
26 }
27 break ;
28 default :
29 Mode = MODE_1 ;
30 }
31 }
Program 1.23: Code for second and third button in ouput_processing.c with green
led
Microcontroller Page 44