完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
您好,我正在尝试使用PIC16F628 A作为一个相当简单的频率计数器。我有两个脉冲-一个长脉冲的RB4(18.8毫秒长,107毫秒之间的脉冲),让我知道一个事件正在发生,另一个脉冲在RB7多次发生,而RB4是高。一旦我计算RB7的脉冲,而RB4是高的,我以简单的串行方式发送RB1的计数。107毫秒有足够的时间这样做而不干扰任何计数。电路是非常简单的- 20 MHz晶体与15个PF帽,5V电源,旁路电源帽,MCLR保持高通过10K电阻器,两个5V脉冲连接-RB4和RB7,以及串行输出线到计算机从RB1。我知道在RB7上使用示波器的脉冲串的一般性质-它非常接近方波- 5美国高,5.6美国低,所以一段时间为10.6美国(94.3千赫)。我的第一个程序如下:我的结果计数是570路太低!我只是不明白——当代码运行在20 MHz时,我应该足够快地执行这些命令(20 MHz / 4=0.2命令),这样我就不会丢失脉冲边沿。因此,我重写了代码,而将timeR1用作异步计数器如下;该代码产生了我所期望的——每个事件大约1774个计数(18.8毫秒/ 10.6个US=1774)。伟大的。但是我需要知道第一个程序到底是什么!有些东西不合算。我真正感到困惑的是,我知道RB7上的脉冲序列的性质随着时间的推移而变化,这是由于一些外部的影响。尽管计数从第一个程序是错误的,它确实表明了正确的变化!另一方面,第二个程序总是显示相同的数字-大约1774。我简直是不知所措!好的,谢谢你的阅读和评论。非常感谢你的任何想法。尊敬的Marshall。
以上来自于百度翻译 以下为原文 Hello, I am trying to use a PIC16F628A as a fairly simple frequency counter. I have two pulses - one long pulse on RB4 (18.8 ms long, 107 ms between pulses) that lets me know an event is occurring, and another pulse on RB7 that occurs multiple times while RB4 is high. Once I count the pulses of RB7 while RB4 is high, I transmit the count out of RB1 in a simple serial fashion. 107 ms is plenty of time to do so without interfering with any counting. The circuit is extremely simple - 20 MHz crystal with 15 pf caps, 5v supply, bypass power cap, MCLR held high through a 10k resistor, two 5v pulse connections - RB4 and RB7, and a serial output line to a computer from RB1. Also, I know the general nature of the pulse train on RB7 using an oscilloscope - it's pretty close to a square wave - 5.0 uS high, 5.6 uS low, so a period of 10.6 uS (94.3 kHz). My first program is as follows; #define _XTAL_FREQ 20000000 #define bit0 1 #define bdr 14 // Sets baud rate to 57,600 #include #include // BEGIN CONFIG #pragma config FOSC = HS // Oscillator Selection bits (HS oscillator) #pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT enabled) #pragma config PWRTE = OFF // Power-up Timer Enable bit (PWRT disabled) #pragma config BOREN = ON // Brown-out Reset Enable bit (BOR enabled) #pragma config LVP = OFF // Low-Voltage (Single-Supply) In-Circuit Serial Programming Enable bit (RB3 is digital I/O, HV on MCLR must be used for programming) #pragma config CPD = OFF // Data EEPROM Memory Code Protection bit (Data EEPROM code protection off) #pragma config CP = OFF // Flash Program Memory Code Protection bit (Code protection off) #pragma config MCLRE = ON //END CONFIG void sendSerialByte(unsigned char data) { unsigned char i; i = 8; RB1 = 0; // set start bit __delay_us(bdr); // wait a full bit time while (i) { if (bit0 & data) // Check the value of the first bit in { RB1 = 1; // data, invert it, and put it out on the wire. } else { RB1 = 0; } data = data >> 1; // Rotate the data one to the right i--; // Decrement the counter __delay_us(bdr); // wait a full bit time } RB1 = 1; // set stop bit __delay_us(bdr); // wait a full bit time __delay_us(bdr); // wait a full bit time __delay_us(bdr); // wait a full bit __delay_us(bdr); // wait a full bit time } int main() { unsigned int freqCtr = 0; unsigned char lowerPart; unsigned char upperPart; int state = 0; int sigVal; TRISB1 = 0; // Use RB1 as an output pin for serial TRISB7 = 1; // Use B7 bit as an input - pulse to be counted TRISB4 = 1; // Use B4 bit as in input - indicates valid info on B7 // Send a few wake up # characters... sendSerialByte(35); sendSerialByte(35); sendSerialByte(35); while(1) { while (RB4) // RB4 pulse is high, so count leading edges on RB7 { sigVal = RB7; // get the value of RB7 if (sigVal != state) // compare RB7 to the current state { if (sigVal == 1) // RB4 must be high and since sigVal is 1 and sigVal != state, this is an edge! { freqCtr++; // Count the edge state = 1; // Change the state from 0 to 1 so I don't count this pulse anymore } else { state = 0; // pulse just ended, set the state back to 0 } } } if (freqCtr > 0) // don't bother reporting any zero data { lowerPart = freqCtr & 255; upperPart = (freqCtr & 65280) >> 8; sendSerialByte(60); sendSerialByte(lowerPart); sendSerialByte(upperPart); sendSerialByte(62); freqCtr = 0; // reset the frequency counter after it's reported. } } return 0; } My resulting count is 570 - way too low! I just don't get it - with the code running at 20 MHz, I should be executing these commands fast enough (20 MHz/4 = 0.2 uS per command) so that I'm not missing pulse edges. So, I rewrote the code and instead used the Timer1 as an asynchronous counter as follows; #define _XTAL_FREQ 20000000 #define bit0 1 #define bdr 14 // Sets baud rate to 57,600 // PIC16F628A Configuration Bit Settings // 'C' source line config statements // CONFIG #pragma config FOSC = HS // Oscillator Selection bits (HS oscillator: High-speed crystal/resonator on RA6/OSC2/CLKOUT and RA7/OSC1/CLKIN) #pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT disabled) #pragma config PWRTE = OFF // Power-up Timer Enable bit (PWRT disabled) #pragma config MCLRE = ON // RA5/MCLR/VPP Pin Function Select bit (RA5/MCLR/VPP pin function is MCLR) #pragma config BOREN = ON // Brown-out Detect Enable bit (BOD enabled) #pragma config LVP = OFF // Low-Voltage Programming Enable bit (RB4/PGM pin has digital I/O function, HV on MCLR must be used for programming) #pragma config CPD = OFF // Data EE Memory Code Protection bit (Data memory code protection off) #pragma config CP = OFF // Flash Program Memory Code Protection bit (Code protection off) // #pragma config statements should precede project file includes. // Use project enums instead of #define for ON and OFF. #include #include void sendSerialByte(unsigned char data) { unsigned char i; i = 8; RB1 = 0; // set start bit __delay_us(bdr); // wait a full bit time while (i) { if (bit0 & data) // Check the value of the first bit in { RB1 = 1; // data, invert it, and put it out on the wire. } else { RB1 = 0; } data = data >> 1; // Rotate the data one to the right i--; // Decrement the counter __delay_us(bdr); // wait a full bit time } RB1 = 1; // set stop bit __delay_us(bdr); // wait a full bit time __delay_us(bdr); // wait a full bit time __delay_us(bdr); // wait a full bit __delay_us(bdr); // wait a full bit time } void main(void) { int state = 0; /* REGISTER 7-1: T1CON ? TIMER1 CONTROL REGISTER (ADDRESS: 10h) * B7 B6 B5 B4 B3 B2 B1 B0 ? ? T1CKPS1 T1CKPS0 T1OSCEN T1SYNC TMR1CS TMR1ON * 0 0 0 0 1 1 1 x * * B7 not used * B6 not used * B5/B4 prescale select bits - 00 for 1:1 * B3 Oscillator enable, set to 1 for input on RB7, set to 0 for input on RB6 * B2 set to 1 for asychronous counter mode * B1 set to 1 for counter mode, not internal timer mode * B0 enable timer * * 0 0 0 0 1 1 1 0 --> 0010 1110 * T1CON = 14, set up properly * T1CON = 15, set up properly * */ T1CON = 14; // set up Timer1, turn it off TMR1H = 0; // set the timer value to 0 TMR1L = 0; TRISB1 = 0; // set B1 up for output - serial data out (pin 7) TRISB4 = 1; // set B4 up for input - used for the slow pulse (pin 10) TRISB7 = 1; // set B7 up for input - used for the counted pulse (pin 13) // I believe this value gets overridden anyway... sendSerialByte(35); // Send ### to say we are alive! sendSerialByte(35); sendSerialByte(35); state = 0; // Set the state to 0 while (1) // Repeat forever { while (RB4) // While the slow pulse is high { if (state == 0) // This condition occurs if RB4 was just detected as high - basically a rising edge detector { T1CON = 15; // Turn on the counter state = 1; // Set the state to 1 - now this loop repeats until RB4 drops RB3 = 0; // Turn RB3 off - RB3 should be the inverse of the slow pulse present at RB4 } } if (state == 1) // State JUST changed - send the data, but only once { T1CON = 14; // RB4 has dropped! Turn off the counter sendSerialByte(60); // Send first delimiter sendSerialByte(TMR1L); // Send counter low byte sendSerialByte(TMR1H); // Send counter high byte sendSerialByte(62); // Send second delimiter state = 0; // Turn off the state in preparation for the next time around // and to make sure we don't send another message for this count TMR1L = 0; // Reset the counter TMR1H = 0; } } return; } This code produces exactly what I'd expect - about 1,774 counts per event (18.8 ms/10.6 uS = 1,774). Great. But I need to understand exactly what that first program is counting! Something just doesn't add up. What's really perplexing to me is that I know that the nature of the pulse train on RB7 changes over time due to some external influences. Despite the count being wrong from the first program, it does indicate the change properly! On the other hand, the second program always shows the same number - about 1,774. I am simply at a loss! Ok, thanks in advance for reading and commenting - any and all thoughts are greatly appreciated. Respectfully, Marshall |
|
相关推荐
4个回答
|
|
我可以认为,当你把数据发送到串口时,你会丢失一些脉冲,或者“机器变得疯狂”,伪RS23的速度是多少?然后,C可能会引入一些巨大的开销,虽然我不确定。
以上来自于百度翻译 以下为原文 I can think that, as you send data to the serial port, you lose some pulses or anyway "the machine gets crazy" Which speed is the pseudo-RS232 going at? Then, C may be introducing some big overhead, though I am not sure. |
|
|
|
嗨,CinziaG,连续剧基本上是57600波特。更具体地说,在我提交串行传输例程的比特等待时,发送每个字节数据所需的总时间为13×BDR US,其中BDR为14 US,每字节产生总共182个U。每个频率报告是四字节,所以传输的总时间是182×4或728 US,不包括命令执行时间,在这个特定的实例中是完全可以忽略的。在毫秒中,这相当于0.728毫秒。因为RB4脉冲之间的时间是107毫秒,所以应该有足够的时间来发送该数据,而不干扰计数。我使用不到1%的可用时间。另外,如果这是问题,你会认为我会在这两个程序中经历这个问题,但是我不。现在,C代码可能会增加开销,但是用这么简单的东西,我希望不是——也许……谢谢,Marshall。
以上来自于百度翻译 以下为原文 Hi CinziaG, The serial is going out at essentially 57,600 baud. More specifically, with the bit waits that I threw in the serial transmit routine, the total time it should take to transmit each byte of data is 13 * bdr uS, where bdr is 14 uS, yielding a total of 182 uS per byte. Each frequency report is four bytes, so the total time of transmit is 182 * 4 or 728 uS, not including command execution time, which in this particular instance is entirely negligible. In milliseconds, this amounts to 0.728 ms. Since the amount of time between RB4 pulses is 107 ms, there should be PLENTY of time to send this data without it interfering with the count. I am using less than 1% of the available time. Plus, if this was the problem, you'd think I would experience the issue in both programs, but I don't. Now, the C code could be adding overhead, but with something so simple, I would hope not - maybe though... Thanks, Marshall |
|
|
|
这将给你每半个周期大约25个机器指令周期(5个US/0.2个U),而这不会与25个机器指令相同(有些将需要2个周期)。我会检查生成的汇编代码,我猜你没有像你想象的那样跑得快(很多C开销),你丢失了脉冲。不确定使用Time1的第二次尝试。
以上来自于百度翻译 以下为原文 That would give you approx. 25 machine instruction cycles per half period (5.0 uS / 0.2 uS) and that will NOT be the same as 25 machine instructions (some will require 2 cycles). I would check the generated assembly code, I will guess that you are not running as fast as you think (lots of c overhead) and you are missing pulses. Not sure about the second attempt using the timer1. |
|
|
|
嗯,是的,你在传播,而不是在计算…有道理……然后我会检查结果代码及其执行速度,是吗?
以上来自于百度翻译 以下为原文 Mmmm yeah, you're transmitting while not counting... makes sense... Then I'd check the resulting code and its sped of execution, yep |
|
|
|
只有小组成员才能发言,加入小组>>
5183 浏览 9 评论
2005 浏览 8 评论
1932 浏览 10 评论
请问是否能把一个ADC值转换成两个字节用来设置PWM占空比?
3178 浏览 3 评论
请问电源和晶体值之间有什么关系吗?PIC在正常条件下运行4MHz需要多少电压?
2229 浏览 5 评论
739浏览 1评论
624浏览 1评论
有偿咨询,关于MPLAB X IPE烧录PIC32MX所遇到的问题
510浏览 1评论
PIC Kit3出现目标设备ID(00000000)与预期的设备ID(02c20000)不匹配。是什么原因
637浏览 0评论
535浏览 0评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-27 17:07 , Processed in 1.294017 second(s), Total 52, Slave 46 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号