51 single chip microcomputer generates 1Hz-5kHz adjustable duty cycle square wave

Publisher:innovation2Latest update time:2017-01-18 Source: eefocus Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere

Notice


1. The change of high and low levels is not suitable in the while loop of the main function, because there must be a delay in the dynamic display of the digital tube and other logical processing. If the time is too long, the high and low level values ​​cannot be changed in time.


2. The execution time of the interrupt must not exceed the timing time, otherwise the next interrupt will come before the interrupt is processed, causing frequency errors.


3. Assuming that the interrupt occurs once every 100us and the interrupt program takes 40us to execute, there are still 70us between the completion of the current interrupt and the arrival of the next interrupt. The remaining time is used to execute the while loop of the main function. Therefore, time should be left for the main function when designing the interrupt.


4. Assume that the original delay function is set to a delay of 1ms, and now the delay function is interrupted once every 100us, and each interruption executes 40us, then the delay time becomes 1*(1+40/100)=1.4ms. In addition to the delay function, other statements will also be interrupted. Therefore, the shorter the timing time, that is, the more frequent the interruption, the shorter the original delay should be, otherwise it will cause the digital tube to flicker, the button to be pressed for a long time, etc.


 


One method is to assign the timing values ​​of the high and low level durations to the timer in turn during the interrupt. This method has a large error when the frequency is high. Testing has found that the frequency is inaccurate due to the reloading of the count value.


Therefore, timer mode 2 (automatic reload mode) with a fixed timing of 50us was later adopted. The count value is increased by one for each interrupt, and then compared with the set value to output high and low levels. The 5k frequency of this method is very accurate, as long as the execution time of the interrupt program does not exceed 50us.

 


For 11.0592M crystal oscillator, the interrupt program takes more than 20us after less than 10 lines of C language, so I set it to 50us timer interrupt. If it is set in this way, the pin state will be inverted in each interrupt, and the maximum square wave of 10k can be obtained. If it is to generate a 5k square wave, the duty cycle can be set to 25, 50, 75. For example, 25% duty cycle means 50us high level and 150us low level.



If the timing time is set smaller, and the interrupt program only has one command to invert the pin, the 50k square wave is the limit.



  1 #include

  2 

  3 typedef unsigned char uint8;

  4 

  5 sbit wave=P1^2; //waveform output

  6 sbit du=P1^0; //segment select latch

  7 sbit we=P1^1; //bit select latch

  8 

  9 #define FNUM 5 //Frequency number

 10 #define DNUM 3 //Duty cycle number

 11 

 12 //Common cathode segment code table

 13 uint8 code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};

 14 

 15 unsigned dnum,fnum;

 16 unsigned count;

 17 

 18 uint8 key_scan(void);

 19 void display(uint8 num[]);

 20 void delayms(unsigned ms);

 twenty one 

 22 void main(void)

 twenty three {

 24 uint8 fsel=4,dsel=2; //Default selection

 25 unsigned long freq[FNUM]={1,10,100,1000,5000}; //frequency

 26 uint8 duty[DNUM]={25,50,75}; //duty cycle

 27 uint8 num[4]={0};

 28 

 29 

 30 TMOD=0x02; //Method 2

 31 TH0=TL0=256-46; //50us    

 32 count=0;

 33 fnum=1000000/50/freq[fsel-1];

 34 dnum=1000000/50/freq[fsel-1]*duty[dsel-1]/100;

 35 

 36 EA=1;

 37 ET0=1;

 38 TR0=1;

 39 

 40 while(1)

 41 {

 42 switch(key_scan())

 43 { // Frequency minus, plus, duty cycle minus, plus, confirm key

 44 case 0:

 45 if(fsel--==1)

 46 fsel=FNUM;

 47 break;

 48 case 1:

 49 if(fsel++==FNUM)

 50 fsel=1;                

 51 break;

 52 case 2:

 53 if(dsel--==1)

 54 dsel=DNUM;        

 55 break;

 56 case 3:

 57 if(dsel++==DNUM)

 58 dsel=1;

 59 break;

 60 case 7:

 61 TR0=0;

 62 count=0;

 63 fnum=1000000/50/freq[fsel-1];

 64 dnum=1000000/50/freq[fsel-1]*duty[dsel-1]/100;

 65 TR0=1;

 66             

 67 break;

 68 default: //No key pressed

 69 break;

 70 }

 71         

 72 //The digital tube displays the selected frequency and duty cycle

 73 num[1]=fsel;    

 74 num[0]=dsel;

 75 display(num);

 76 }

 77 }

 78 

 79 

 80 // Scan the matrix keyboard using the flip method and return the key value

 81 uint8 key_scan(void)

 82 {

 83 uint8 key,i,ret=0xff; //No key is pressed, return 0xff

 84 P2=0xf0;

 85     

 86 if(P2!=0xf0)

 87 {

 88 delayms(10);

 89 if(P2!=0xf0)

 90 {

 91 key=P2;

 92 P2=0x0f;

 93 key|=P2;

 94 while(P2!=0x0f)

 95 ;

 96 for(i=0;(key>>i)&0x01;i++)

 97 ;

 98 ret=3-i;

 99 for(i=4;(key>>i)&0x01;i++)

100 ;

101 ret+=(7-i)*4;

102 }

103 }

104 return ret;

105 }

106 

107 //Digital tube dynamic display

108 void display(uint8 num[])

109 {

110 uint8 i;

111 for(i=0;i<4;i++)

112 {

113 P0=0xff; //Eliminating

114 we=1;

115 we=0;

116     

117 P0=table[num[i]];

118 du=1;

119 du=0;

120 P0=~(1<

121 we=1;

122 we=0;

123 delayms(1);        

124 }

125 }

126 

127 void timer0(void) interrupt 1

128 {

129 count++;

130 

131 if(count==fnum)//frequency count value

132 {

133 count=0;

134 wave=1;

135 }

136 else if(count==dnum)//duty cycle count value

137 wave=0;

138 

139 }

140 

141 void delayms(unsigned ms)

142 {

143 uint8 i=11; //Reduce the delay

144 while(ms--)

145 while(i--)

146 ;

147 }


Reference address:51 single chip microcomputer generates 1Hz-5kHz adjustable duty cycle square wave

Previous article:51 MCU connected to 24C02-C language test code
Next article:Microcontroller Learning Notes (Part 3) - Digital Tube Display

Latest Microcontroller Articles
  • Download from the Internet--ARM Getting Started Notes
    A brief introduction: From today on, the ARM notebook of the rookie is open, and it can be regarded as a place to store these notes. Why publish it? Maybe you are interested in it. In fact, the reason for these notes is ...
  • Learn ARM development(22)
    Turning off and on interrupts Interrupts are an efficient dialogue mechanism, but sometimes you don't want to interrupt the program while it is running. For example, when you are printing something, the program suddenly interrupts and another ...
  • Learn ARM development(21)
    First, declare the task pointer, because it will be used later. Task pointer volatile TASK_TCB* volatile g_pCurrentTask = NULL;volatile TASK_TCB* vol ...
  • Learn ARM development(20)
    With the previous Tick interrupt, the basic task switching conditions are ready. However, this "easterly" is also difficult to understand. Only through continuous practice can we understand it. ...
  • Learn ARM development(19)
    After many days of hard work, I finally got the interrupt working. But in order to allow RTOS to use timer interrupts, what kind of interrupts can be implemented in S3C44B0? There are two methods in S3C44B0. ...
  • Learn ARM development(14)
  • Learn ARM development(15)
  • Learn ARM development(16)
  • Learn ARM development(17)
Change More Related Popular Components

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

About Us Customer Service Contact Information Datasheet Sitemap LatestNews


Room 1530, 15th Floor, Building B, No.18 Zhongguancun Street, Haidian District, Beijing, Postal Code: 100190 China Telephone: 008610 8235 0740

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号