GD32E231 DIY Contest (5) - Complete the driver and settings of DS1302 and the recognition of long and short keys[Copy link]
The driver of DS1302 was completed before the holiday. The date and time can be read from DS1302 and written. But the date and time need to be adjusted by using a button. It took nearly a week to make a button play multiple roles. The following figure shows the test process:
In order to reduce the communication with DS1302, I took the date and time value of DS1302 once a minute and updated the display. The number of seconds is generated by the system ticking millisecond clock as the basis for counting seconds and reading DS1302 timing. Although there will be a certain difference in time (no more than 1 minute), fortunately, my application does not require high time accuracy, which is enough to meet the needs. The following is the code for counting seconds and timing reading DS1302. This code is placed in a loop.
if(ms >999) { flag = !flag; ms = 0; /* turn on LED1 */ gpio_bit_toggle(GPIOA,GPIO_PIN_7); seco++; //Seconds counting if(seco > 59) { if(mode==0) DS1302_read_date(); //Read DS302 data once a minute } display_date(); //Display date and time if(mode > 0) display_flash();//Flash to display adjustment items }
复制代码
The global variable ms is incremented in the system tick interrupt, and is judged in the main loop whether it exceeds 999. Since the main loop is also affected by key processing and other matters, the second counting is definitely not accurate. However, the correct time will be read from DS1302 once a minute, so this error is not a big deal. Since the LCD5100 I use can only display 14 characters per line (I use a 5*8 dot matrix with an empty column), the year, month, day, hour, minute, and second can be displayed in full, but there is no separator, so it is not easy to recognize. I have to use the method of displaying the year, month, and day in turn, and displaying the hour, minute, and second in a fixed manner, as shown below: Displaying the year and time [attach] 412484 [/attach] Displaying the month, day, and time [attach] 412485 [/attach] When it came to identifying long and short key presses, I fell into a pit and made no progress for 5 to 6 days. Since there was only one user button on the development board, and I needed to identify at least two button states, I started using the key interrupt method. I tried repeatedly but couldn't find a reliable identification method. During this period, I posted for help and searched for multiple modular key processing codes on the Internet, but none of them worked for various reasons. After struggling for nearly a week, I finally decided to use the most primitive polling method, using a loop and delay to achieve the goal. Although this is inefficient, it has no effect on my project. I now use four button states, namely tap, slightly long press (less than one second), long press (slightly more than one second), and super long press (more than two seconds). The following is the code for key acquisition:
keys = 0; while(gd_eval_key_state_get(KEY_WAKEUP)) { keys++; delay_1ms(50); } if(keys > 0) //A key is pressed key_processing(); [/code After actual testing, the keys value obtained when tapping is about 2~3, the value of slightly long pressing is about 6~9, and the value of long pressing is about 13~17. I check the value of keys in the program. If it is less than 5, it is considered a tap, between 5~10 is judged as a slightly long press, between 11~20 is judged as a long press, and more than 20 is considered as a super long press. After solving the problem of long and short key recognition, the date and time adjustment code can be easily debugged and passed. The following is the code for checking the value range when setting the date and time, which can ensure that illegal dates and times are not entered. [code] switch(mode) { case 1: year++; if(keys>5) year += 4; if(year > 2030) year = 2019; break; case 2: mon++; if(keys>5) mon += 4; if(mon > 12) mon = 1; break; case 3: day++; if(keys>5) day += 4; if(day > 31) day = 1 >30) & (mon==4 | mon==6 | mon==9 | mon==11)) day = 1; if((mon==2) & (day>28)){ if(year%4 != 0){ day = 1; } else{ if(day>29) day = 1; } } break; case 4: hour++; if(keys>5) hour += 4; if(hour > 23) mon = 0; break; case 5: minu++; if(keys>5) minu += 4; if(minu > 59) minu = 0; break;
复制代码
To simplify the operation, I limit the year value to the range of 2019~2030. Pressing the key will increase the corresponding value by 1, pressing it for a while will increase it by 5, and pressing it for a while will change the adjustment item. The adjustment items are carried out in the order of year, month, day, hour and minute. The default value of second is 0. The following figure shows the year setting: