// Enable digital tubes No. 0 to No. 7 respectively (use AND (&) to enable)
static const uint8_t segment_index[8]= { 0,1,2,3,4,5,6,7 };
typedef struct
{
uint8_t *seg_index; //bit select port data
uint8_t *seg_code; //Segment selection port data
uint8_t index; // Enable the index digital tube
uint8_t data_part[_countof(segment_index)]; // 8 data sent to the digital tube [0:7] for display
uint32_t data; // Data for display, it will be split into data_part[] for storage
}T_SEG_LED_DISPLAY_CTRL,*pT_SEG_LED_DISPLAY_CTRL;
static T_SEG_LED_DISPLAY_CTRL LED_display_ctrl = { .seg_index = (uint8_t *)(&PORTA),
.seg_code = (uint8_t *)(&PORTB),
.index = 0,
.data_part = { 0,0,0,0,0,0,0,0 },
.data = 0
};
static pT_SEG_LED_DISPLAY_CTRL p_LED_display_ctrl = &LED_display_ctrl;
// ==========================================================================================================
//LED digital tube hardware initialization
//
// ==========================================================================================================
void Mod_LED_display_init(void)
{
// Digital tube bit selection enable (74HC138 chip enable): output high level
DDRC |= (IO_OUTPUT << DDC7);
PORTC |= (IO_OUTPUT << PC7 );
// Segment selection control: PORTB is initialized to: output low level
DDRB = 0xFF;
PORTB = 0x00;
// Bit selection control: PORTA[2:0] is initialized to: output low level (select the 0th digital tube)
DDRA |= (IO_OUTPUT << DDA0) |(IO_OUTPUT << DDA1) | (IO_OUTPUT << DDA2);
PORTA &= ~((1 << PA0 ) |(1 << PA1 ) | (1 << PA2 ));
}
// ==========================================================================================================
// Refresh the LED digital tube display data
//
// Parameter: static index Split an 8-digit decimal number into 8 cells of the array, index is the subscript of the current array element
// Split only 1 bit at a time, the part of the data exceeding 8 bits will be automatically truncated
//
// Query message: EVENT_SEG_UPDATE
// Message parameter: 32-bit value
// Send message: None
//
// illustrate:
// (0). Refresh regularly in the system timer or task scheduler (scheduled as a task)
// (1). An 8-digit number needs to be split. Each split (plus refresh display) takes 170us (including the time to enter and exit the task function)
// (2). In fact, every time data is updated, the value in the 8-bit array p_LED_display_ctrl->data_part needs to be recalculated
// (3). If data is a 3-digit number (such as 120), it only needs to be calculated 3 times, which means 3 calculations will take about 170us.
// After data=0, no time-consuming calculation is performed, but the corresponding element in the array p_LED_display_ctrl->data_part is directly assigned a value of 0.
// (4). If data is 0 or has not changed, no calculation is required. In this case, this task function takes 11.32us
//
// ==========================================================================================================
void task_Mod_LED_display_update(void)
{
uint8_t temp = 0;
volatile static uint8_t index = _countof(segment_index);
// --------------------------------------------------------------------
// Query message
if(TRUE == sys_event_peek(EVENT_SEG_UPDATE, &p_LED_display_ctrl->data))
{
index = 0; // If updated data is obtained, data splitting will be started
}
// ---------------------------------------------------
// Main text
// ---------------------------------------------------
// Split 8-bit decimal data into data_part[] (starting from data position 0)
if(index < _countof(segment_index))
{
if(0 == p_LED_display_ctrl->data) { temp = 0; }
else { temp = p_LED_display_ctrl->data % 10UL; }
p_LED_display_ctrl->data_part[_countof(segment_index) - 1 - index] = temp;
if(0 != p_LED_display_ctrl->data) { p_LED_display_ctrl->data = p_LED_display_ctrl->data / 10UL; }
index++;
}
// --------
// Refresh the display
// Turn off the current digital tube
*p_LED_display_ctrl->seg_code = segment_code[_countof(segment_code) - 1];
// Switch to the next digital tube
p_LED_display_ctrl->index++;
if(p_LED_display_ctrl->index > (_countof(segment_index) - 1))
{
p_LED_display_ctrl->index = 0;
}
// Modify bit selection and display
*p_LED_display_ctrl->seg_index |= segment_index[_countof(segment_index) - 1];
*p_LED_display_ctrl->seg_index &= segment_index[p_LED_display_ctrl->index];
*p_LED_display_ctrl->seg_code = segment_code[p_LED_display_ctrl->data_part[segment_index[p_LED_display_ctrl->index]]];
// ---------------------------------------------------
// Send a message
}
// ==========================================================================================================
//LED digital tube display (decimal)
//
// illustrate:
// (1): If necessary, the display format can be made into event EVENT_SEG_FORMAT with message: MSG_SEG_HEX (display the result in hexadecimal)
// MSG_SEG_DEC (display the result in decimal)
// MSG_SEG_OCT (display the result in octal)
// MSG_SEG_BIN (display the result in binary)
//
// ==========================================================================================================
void Mod_LED_display(uint32_t data)
{
sys_event_post(EVENT_SEG_UPDATE, data);
}
For details on message management and task scheduling, see: "A005-Software Structure-From Front-end and Back-end to Scheduler".
-------------------------------------------------------------------------------------------------------------------------------------
Step 6: Display in the specified base
Improve:
1. You can specify to display data from binary to hexadecimal
2. Further organize the task functions under the message mechanism
Drv_Sys.c:
// ==========================================================================================================
// Set the data format (range: [2,16])
//
// ==========================================================================================================
void Drv_sys_set_digital_format(uint8_t format)
{
if((format >= 2) && (format <= 16))
{
sys_event_post(EVENT_DIGITAL_FORMAT, format);
}
}
Mod_LED_display.c:
// ==========================================================================================================
// Copyright (c) 2016 Manon.C // // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and // associated documentation files (the "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject // to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING // BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // // ------------------------------------ // This article defines the 8-segment LED digital tube driver under Atmega16 // The corresponding driving circuit in the article: http://blog.csdn.net/manon_des_source/article/details/51783675 // // ------------------------------------ // Include: // // ========================================================================================================== #include "Mod_LED_Displayer.h" // Segment code (common cathode == high level lights up) static const uint8_t segment_code[17]= { 0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f, // 0 - 9 0x77,0x7c,0x39,0x5e,0x79,0x71, // A - F (AND with it to get the value of a certain 1-digit digital tube) 0x00 // All off (or with it to extinguish the display of the currently selected digital tube) }; // Bit code (low level enable) (use 74HC138 strobe bit selection) // Enable digital tubes No. 0 to No. 7 respectively (use AND (&) to enable) static const uint8_t segment_index[8]= { 0,1,2,3,4,5,6,7 }; typedef struct { uint8_t *seg_index; //bit select port data uint8_t *seg_code; //Segment selection port data uint8_t index; // Enable the index digital tube uint8_t format; //Data display format, range: [2,16] uint8_t set_format; // Need to set a new display format uint8_t set_data; // There is new display data uint8_t data_part[_countof(segment_index)]; // 8 data sent to the digital tube [0:7] for display uint8_t data_index; // When splitting data into data_part[], it is used as the index of data_part uint32_t data; // Data for display, it will be split into data_part[] for storage uint32_t data_copy; // Needed for data backup and format reset }T_SEG_LED_DISPLAY_CTRL,*pT_SEG_LED_DISPLAY_CTRL; static T_SEG_LED_DISPLAY_CTRL LED_display_ctrl = { .seg_index = (uint8_t *)(&PORTA), .seg_code = (uint8_t *)(&PORTB), .index = 0, .format = 10, // Display in decimal format by default .set_format = FALSE, .set_data = FALSE,
Previous article:Atmega16 - BSP and Task List
Next article:A005-Software Structure-From Frontend and Backend to Scheduler
Recommended ReadingLatest update time:2024-11-17 11:57
- Popular Resources
- Popular amplifiers
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
- Innolux's intelligent steer-by-wire solution makes cars smarter and safer
- 8051 MCU - Parity Check
- How to efficiently balance the sensitivity of tactile sensing interfaces
- What should I do if the servo motor shakes? What causes the servo motor to shake quickly?
- 【Brushless Motor】Analysis of three-phase BLDC motor and sharing of two popular development boards
- Midea Industrial Technology's subsidiaries Clou Electronics and Hekang New Energy jointly appeared at the Munich Battery Energy Storage Exhibition and Solar Energy Exhibition
- Guoxin Sichen | Application of ferroelectric memory PB85RS2MC in power battery management, with a capacity of 2M
- Analysis of common faults of frequency converter
- In a head-on competition with Qualcomm, what kind of cockpit products has Intel come up with?
- Dalian Rongke's all-vanadium liquid flow battery energy storage equipment industrialization project has entered the sprint stage before production
- New breakthrough! Ultra-fast memory accelerates Intel Xeon 6-core processors
- New breakthrough! Ultra-fast memory accelerates Intel Xeon 6-core processors
- Consolidating vRAN sites onto a single server helps operators reduce total cost of ownership
- Consolidating vRAN sites onto a single server helps operators reduce total cost of ownership
- Allegro MicroSystems Introduces Advanced Magnetic and Inductive Position Sensing Solutions at Electronica 2024
- Car key in the left hand, liveness detection radar in the right hand, UWB is imperative for cars!
- After a decade of rapid development, domestic CIS has entered the market
- Aegis Dagger Battery + Thor EM-i Super Hybrid, Geely New Energy has thrown out two "king bombs"
- A brief discussion on functional safety - fault, error, and failure
- In the smart car 2.0 cycle, these core industry chains are facing major opportunities!
- These useful information and development boards can help you easily play with STM32/STM8
- MTK7686 serial port transparent transmission
- How to design the mobile phone power-on circuit
- Request expert explanation
- Develop good programming style
- what(): couldn't open /dev/video0
- C2000 floating point calculation notes - differences between CPU and CLA and error handling techniques
- EEWORLD University ---- Theoretical basis of IoT terminal development
- DIY practical household constant current charger
- Tips for implementing I2C with MSP