|
本帖最后由 兔包公 于 2025-6-3 21:04 编辑
书从何起,废话开始,情况大概是这样,P5.4输出SYSclk/4的频率,直连CCP0/p1.1脚测脉冲宽度,宽度数据通过串口1发给手机。
通过本人几翻修改,测试下来,收到的数据反馈似乎对不上,实属不知如何下手。
几翻测试
①,串口部分,基本无问题。
②,p5.4输出,基本无问题,万表能测到6Mhz,刚好等于主时钟24M/4。
③,数据转10进制字符串,基本无问题。
④,从分析来看,6M这个频率下,按理PCA的16位计数器,应该不会溢出,但收到的数据大的离谱。
⑤,尝试在pca中断函数里,用一个变量去记录CCF0中断次数,再在主函数判断,只发送前10几个数据,还是不对,串口发送效果也不理想。
⑥,从手册来看,这频率应该是在能测量的范围内的,几翻无果后,怀疑频率太快了,于是又使用定时器0,P0.0产生500hz的,直连CCP0/p1.1去测,还是不对,心烦 。
一个奇怪的现象,我刚开始用万表去测p00脚的频率,一直没有数据,但当我用黑表笔去碰一下3.3v供电脚再拿开,500hz就出来了,甚至完全断开2表笔,只用红笔去测,竟然也显示500hz,但是如果你黑笔接地,红笔去测,又测不到频率,奇了怪了?什么问题,双向IO口驱动电流不够??万表问题??操作问题??鬼现象???
⑦,尝试别的写法,用u16 CCAP0_tmp去接收捕获寄存器的值,再处理串口发送。
CCAP0_tmp = CCAP0H;
CCAP0_tmp = (CCAP0_tmp << 8) + CCAP0L;
还是不对。
⑧,按我的理解,主时钟24M,周期1/24约等于41.667ns,每来个时钟,PCA的16位计数器+1,也就是每41.667ns计数器+1,6M的频率,周期1/6约等于166.667ns,那么计数器的值的,敞开误差不讲,应该约为4左右,那么捕获寄存器2次的值相减应该为4上下,再对。这么理解是否正确???
请教下大婶,错在哪里?该如何?
就这样,谢谢观看。
代码如下,基于sdcc语法编译。
…………………………………我是分割线…………………………
- #include "stc15.h"
- #include <stdlib.h> //使用其__uitoa(unsigned int, char *, unsigned char)函数,u16转字符串
- //使用其__ultoa(unsigned long, char *, unsigned char)函数,u32转字符串
-
- /*宏定义*/
- #define FOSC 24000000 //系统频率
- #define BAUD 115200 //串口波特率
- #define NONE_PARITY 0 //无校验
- #define ODD_PARITY 1 //奇校验
- #define EVEN_PARITY 2 //偶校验
- #define MARK_PARITY 3 //标记校验
- #define SPACE_PARITY 4 //空白校验
- #define PARITYBIT EVEN_PARITY //取校验位为偶校验
- #define UART1_BUF_LENGTH 32 //串口缓冲数据长度
- #define CCP_S0 0x10 //P_SW1.4 //P_SW1第四位
- #define CCP_S1 0x20 //P_SW1.5 //P_SW1第五位
- //定时器0做16位自动重装, 中断频率为1000HZ,中断函数从P00取反输出500HZ方波信号.
- #define Timer0_Reload (FOSC / 1000) //Timer 0 中断频率, 1000次/秒
- /*变量声明*/
- __bit busy; //串口忙碌标记
- u8 __idata RX1_Buffer[UART1_BUF_LENGTH]; //接收缓冲
- u8 RX1_Cnt; //接收计数
- u8 cnt; //存储PCA计时溢出次数
- u32 count0; //记录上一次的捕获值
- u32 count1; //记录本次的捕获值
- u32 length; //存储信号的时间长度(count1 - count0)
- char length_str[32]=""; //信号时间长度转为字符串,用于串口发送
- /*函数声明*/
- void delay_ms(u16 ms);
- void Uart1_config(void);
- void SendData(u8 dat);
- void SendString(char *s);
- void PCA_config(void);
- void Timer0_config(void);
- /*主函数*/
- void main(void)
- {
- P0M0 =0; //P0准双向
- P0M1 =0;
- P1M0 =0;
- P1M1 =0; //P1准双向
- P5M0 =0;
- P5M1 =0; //P5准双向
- Uart1_config();
- PCA_config();
- Timer0_config();
- EA = ENABLE; //使能总中断
- //CLK_DIV = 0x40; //0100,0000 P5.4输出频率SYSclk
- //CLK_DIV = 0x80; //1000,0000 P5.4输出频率SYSclk/2
- CLK_DIV = 0xC0; //1100,0000 P5.4输出频率SYsclk/4
- P00 = 0; //引脚P00,先为0,低电平
- TR0 =ENABLE ; //定时器0开始运行
- delay_ms(500); //延时,等待P5.4输出频率稳定,
- CR = ENABLE; //使能PCA开始工作
- SendString("STC15W4K56S4 PCA Uart Test !\r\n");
- while(1){
- __ultoa(length, length_str, 10); //转为10进制字符串
- SendString("length = ");
- SendString(length_str);
- SendString("\n");
- }
- }
- /*软件延时函数*/
- void delay_ms(u16 ms)
- {
- u16 i;
- do{
- i = FOSC / 13000;
- while(--i) ;
- }while(--ms);
- }
- /*串口1配置函数*/
- void Uart1_config(void)
- {
- #if (PARITYBIT == NONE_PARITY)
- SCON = 0x50; //8位可变波特率
- #elif (PARITYBIT == ODD_PARITY) || (PARITYBIT == EVEN_PARITY) || (PARITYBIT == MARK_PARITY)
- SCON = 0xda; //9位可变波特率,校验位初始为1
- #elif (PARITYBIT == SPACE_PARITY)
- SCON = 0xd2; //9位可变波特率,校验位初始为0
- #endif
- T2L = (65536 - (FOSC/4/BAUD)) & 0x00FF; //设置波特率重装值,低8位
- T2H = (65536 - (FOSC/4/BAUD))>>8; //高8位
- AUXR = 0x14; //启动定时器2,1T模式
- AUXR |= 0x01; //选择定时器2为串口1的波特率发生器
- ES = ENABLE; //使能串口1中断
- }
- /*串口1中断函数*/
- void Uart1_int(void) __interrupt UART1_VECTOR
- {
- if (RI) {
- RI = 0; //清除RI位
- RX1_Buffer[RX1_Cnt] = SBUF;
- if(++RX1_Cnt >= UART1_BUF_LENGTH) RX1_Cnt = 0; //防溢出
- }
- if (TI) {
- TI = 0; //清除TI位
- busy = 0; //清忙标志
- }
- }
- /*发送一个字节*/
- void SendData(u8 dat)
- {
- while (busy);
- ACC = dat; //获取校验位P (PSW.0)
- if (P) //根据P来设置校验位
- {
- #if (PARITYBIT == ODD_PARITY)
- TB8 = 0; //设置校验位为0
- #elif (PARITYBIT == EVEN_PARITY)
- TB8 = 1; //设置校验位为1
- #endif
- }
- else {
- #if (PARITYBIT == ODD_PARITY)
- TB8 = 1; //设置校验位为1
- #elif (PARITYBIT == EVEN_PARITY)
- TB8 = 0; //设置校验位为0
- #endif
- }
- busy = 1;
- SBUF = ACC; //写数据到UART数据寄存器
- }
- /*发送字符串*/
- void SendString(char *s)
- {
- while (*s) //检测字符串结束标志
- {
- SendData(*s++); //发送当前字符
- }
- }
- /*PCA配置函数*/
- void PCA_config(void)
- {
- //选择引脚
- ACC = P_SW1;
- ACC &= !(CCP_S0 | CCP_S1); //CCP_S0=0 CCP_S1=0
- P_SW1 = ACC; //(P1.2/ECI, P1.1/CCP0, P1.0/CCP1, P3.7/CCP2)
-
- // ACC = P_SW1;
- // ACC &= !(CCP_S0 | CCP_S1); //CCP_S0=1 CCP_S1=0
- // ACC |= CCP_S0; //(P3.4/ECI_2, P3.5/CCP0_2, P3.6/CCP1_2, P3.7/CCP2_2)
- // P_SW1 = ACC;
- // ACC = P_SW1;
- // ACC &= !(CCP_S0 | CCP_S1); //CCP_S0=0 CCP_S1=1
- // ACC |= CCP_S1; //(P2.4/ECI_3, P2.5/CCP0_3, P2.6/CCP1_3, P2.7/CCP2_3)
- // P_SW1 = ACC;
- CCON = 0; //初始化PCA控制寄存器
- //PCA定时器停止
- //清除CF标志
- //清除模块中断标志
- CL = 0; //PCA的16位计数器— 低8位CL和高8位CH
- CH = 0;
- CCAP0L = 0; //PCA捕捉/比较寄存器 — CCAPnL(低位字节)和CCAPnH(高位字节)
- CCAP0H = 0;
- CMOD = 0x09; //设置PCA时钟源为系统时钟,且使能PCA计时溢出中断
- CCAPM0= 0x21; //PCA模块0为16位捕获模式(上升沿捕获,
- //可测从高电平开始的整个周期),且产生捕获中断
- // CCAPM0= 0x11; //PCA模块0为16位捕获模式(下降沿捕获,
- //可测从低电平开始的整个周期),且产生捕获中断
- //CCAPM0= 0x31; //PCA模块0为16位捕获模式(上升沿/下降沿捕获,
- //可测高电平或者低电平宽度),且产生捕获中断
- cnt = 0;
- count0 = 0;
- count1 = 0;
- length = 0;
- }
- /*PCA中断处理函数*/
- void PCA_int(void) __interrupt PCA_VECTOR
- {
- if (CF)
- {
- CF = 0;
- cnt++;
- }
- if (CCF0)
- {
- CCF0 = 0;
- count0 = count1; //备份上一次的捕获值
- ((u8 *)&count1)[3] = CCAP0L; //保存本次的捕获值
- ((u8 *)&count1)[2] = CCAP0H;
- ((u8 *)&count1)[1] = cnt;
- ((u8 *)&count1)[0] = 0;
- length = count1 - count0; //计算两次捕获的差值,即得到时间长度
- }
- }
- /*定期器0配置函数*/
- void Timer0_config(void)
- {
- TR0 =DISABLE; //停止计数
- #if (Timer0_Reload < 64) // 如果用户设置值不合适, 则不启动定时器
- #error "Timer0设置的中断过快!"
- #elif ((Timer0_Reload/12) < 65536) // 如果用户设置值不合适, 则不启动定时器
- ET0 = 1; //允许中断
- // PT0 = 1; //高优先级中断
- TMOD &= !0x03;
- TMOD |= 0; //工作模式, 0: 16位自动重装, 1: 16位定时/计数, 2: 8位自动重装, 3: 16位自动重装, 不可屏蔽中断
- // TMOD |= 0x04; //对外计数或分频
- TMOD &= !0x04; //定时
- // INT_CLKO |= 0x01; //输出时钟
- INT_CLKO &= !0x01; //不输出时钟
- #if (Timer0_Reload < 65536)
- AUXR |= 0x80; //1T mode
- TH0 = (u8)((65536 - Timer0_Reload) / 256);
- TL0 = (u8)((65536 - Timer0_Reload) % 256);
- #else
- AUXR &= !0x80; //12T mode
- TH0 = (u8)((65536 - Timer0_Reload/12) / 256);
- TL0 = (u8)((65536 - Timer0_Reload/12) % 256);
- #endif
-
- #else
- #error "Timer0设置的中断过慢!"
- #endif
- }
- /*定期器0中断处理函数*/
- void Timer0_int (void) __interrupt TIMER0_VECTOR
- {
- P00 = !P00;
- }
复制代码
|
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?立即注册
x
打赏
-
查看全部打赏
|