找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2214|回复: 16
收起左侧

求解,STC8F2K16S2单片机最快定时

[复制链接]
ID:734017 发表于 2021-10-19 01:16 | 显示全部楼层 |阅读模式
先上图 6a76cde9c3f8d5ea6ed21747f816155.jpg dc89524b2671876b9718fd5dd7a27eb.jpg
这是别人工程师用8F2K16S写的,内部高精度24M,1T  汇编

这个是IO口P1.1输出PWM可调占空比
占空比增加0.5 %  时间加0.4us,这里可能有中断延时。也可能用计数模式。时间不是很准。按0.4US计数,分辨率有200档
其它还有P1.0    周期20MS  50K  可调
P5.5 20MS 50K 可调
P2.3   P2.4 P2.5 P2.6   这4个IO输出在60K 左右,可调 占空比
串口1   115200  只接收
加上其它IO 取反控制。以上功能全用,不冲突
重点是P1.1这路PWM
我用C语言做不了这么快,用定时器只输出一路P1.1PWM,只能用1US中断 再快就会出错。如果串口优先最高。对其他定时器影响如何计算。

回复

使用道具 举报

ID:429003 发表于 2021-10-19 09:12 | 显示全部楼层
对这款单片机不熟悉,但是精度能控制到0.4us并且是稳定的,肯定不是靠中断控制IO实现的,应该是硬件定时器自动完成的!
串口接收可用DMA或中断加定时器实现,几乎不占CPU时间。
回复

使用道具 举报

ID:277550 发表于 2021-10-19 09:26 | 显示全部楼层
仅做单一功能,会稳定一些
回复

使用道具 举报

ID:276663 发表于 2021-10-19 10:35 | 显示全部楼层
不会选带PWM输出的IC吗?非要用这一款?
既然别人用汇编,你要知道汇编的效率,执行中断的速度快。
回复

使用道具 举报

ID:734017 发表于 2021-10-19 11:03 | 显示全部楼层
IdeaMing 发表于 2021-10-19 10:35
不会选带PWM输出的IC吗?非要用这一款?
既然别人用汇编,你要知道汇编的效率,执行中断的速度快。

产品已成形了。其中有很多苦处。不好说。
其它都好搞,就是这个太快了
回复

使用道具 举报

ID:734017 发表于 2021-10-19 11:03 | 显示全部楼层
xstong 发表于 2021-10-19 09:12
对这款单片机不熟悉,但是精度能控制到0.4us并且是稳定的,肯定不是靠中断控制IO实现的,应该是硬件定时器 ...

请指导一下
回复

使用道具 举报

ID:734017 发表于 2021-10-19 11:04 | 显示全部楼层
devcang 发表于 2021-10-19 09:26
仅做单一功能,会稳定一些

拿别人的,不良率5/1000
回复

使用道具 举报

ID:401564 发表于 2021-10-19 11:21 | 显示全部楼层
0.4uS已经是到一个时钟的长度
可能是用的是自动重载功能,这样,进入中断就不用对计数器进行操作了
PWM也可以是达到1个时钟的精度,也不用进入中断操作的,调节占空比的时候可能要慢一点
回复

使用道具 举报

ID:734017 发表于 2021-10-19 13:59 | 显示全部楼层
Y_G_G 发表于 2021-10-19 11:21
0.4uS已经是到一个时钟的长度
可能是用的是自动重载功能,这样,进入中断就不用对计数器进行操作了
PWM也可 ...

C163557_7FC7AC4F38C1270EEB607D94DD1F8DD7.pdf (7.59 MB, 下载次数: 13)
回复

使用道具 举报

ID:213173 发表于 2021-10-19 13:59 | 显示全部楼层
楼主计算的时间与示波器显示不符
回复

使用道具 举报

ID:734017 发表于 2021-10-19 14:11 | 显示全部楼层
wulin 发表于 2021-10-19 13:59
楼主计算的时间与示波器显示不符

我换一个看看
回复

使用道具 举报

ID:401564 发表于 2021-10-19 16:30 | 显示全部楼层
happy2058 发表于 2021-10-19 13:59
没有计数,改变初值,占空比不好改。大哥帮我看看,手册上最后一个功能:增强型双数据指针,是否可以 ...

那就用16位定时器来输出PWM
在定时器中断中实现PWM占空比,调节在主程序调节
在定时器中断中加载TH0,TL0
在主程序调节TH0,TL0
汇编是效率高,不是速度快,C在99%的情况下都可以达到汇编的速度的,你的不快,只是方法不对而已
把你的代码上传,看一下你是怎么调节PWM的,不要截图
手头上没有示波器,不好搞
我以前就是用汇编的,除了占用空间小点,暂时没有体验到汇编的其它优点
回复

使用道具 举报

ID:734017 发表于 2021-10-19 22:01 | 显示全部楼层
Y_G_G 发表于 2021-10-19 16:30
那就用16位定时器来输出PWM
在定时器中断中实现PWM占空比,调节在主程序调节
在定时器中断中加载TH0,TL0 ...

一般都这样写,这是两组20MS 50K的  要求不高,就这样写了。上图那个0.4US的是另一组功能。我用0.5US试过,直接卡死
void key_service()                大循环扫描串口缓存                                                
{
        key_service_lock=0;                串口标志位
switch(buf[1])                                                                
                        {
                        case 0X79:


if(        buf[3]==0x09)                                                               
                                {                       
                                        memset(buf, 0, 16); //清串口缓存
                                        if(clok<20)
                                        {
                                        clok++;
                                        Energy_TXD(clok,         0x03 ,Energy_current_X[1],Energy_current_X2[1]); //发送屏幕显示
                                        }
                                }
                                if(        buf[3]==0x10)                                                               
                                {                       
                                        memset(buf, 0, 16);
                                        if(clok>=1)
                                        {
                                        clok--;
                                                                               
                                        Energy_TXD(clok,         0x03 ,Energy_current_X[1],Energy_current_X2[1]);
                                        }
if(        buf[3]==0x12)                                                               
                                {       
                                        memset(buf, 0, 16);
                                        if(RF>=1)
                                        {
                                        RF--;
                                        Energy_TXD(RF, 0x03,Energy_current_X[2],Energy_current_X2[2]);       
                                        }
                                }
                                if(        buf[3]==0x13)                                                               
                                {                       
                                        memset(buf, 0, 16);
                                        if(ul<20)
                                        {
                                        ul++;
                                        Energy_TXD(ul,         0x03,Energy_current_X[3],Energy_current_X2[3]);       
                                        }
break;       
case 0X78:
break; default:break;
**********************
**********************



code unsigned char ul_PWMCounterSATAT[52]={0,1,2,3,4,******************,0};            
code unsigned char clok_PWMCounterSATAT[52]={0,1,2,3,4,******************,0};
void InterruptTimer0() interrupt 1                //400US一次        20MS 50K  16位自动重装       
{       
                  if (ul_satar|clok_satar)             大循环标志位,两个功能 P2.0  P2.1   
         {
                          PWMCounter++;                                       
                           if(ul_satar)                             //P2.0  
                           {  
                                if(PWMCounter<=ul_PWMCounterSATAT[ul])
                                        PWM=1;
                                else PWM=0;
                           }
                        if (clok_satar)           //  P2.1
                        {               
                                if(PWMCounter<=clok_PWMCounterSATAT[clok])
                                        clok_PWM=0;
                                else clok_PWM=1;
                        }
                        if(PWMCounter>=50)
                                PWMCounter=0;
        }
                else
        {
                        PWMCounter=0;
        }
}


***********************************************************用0.5US做PWM 程序不动,卡死。
void TM1_Isr() interrupt 3         0.5US                               
{
       
       
                                RF_PWMCounter++;                                       
                          
                                if(RF_PWMCounter<=40)
                                        P1_1=1;
                                else P1_1=0;
                         
                                if(RF_PWMCounter>=200)
                                        RF_PWMCounter=0;
       
                       
}




回复

使用道具 举报

ID:401564 发表于 2021-10-20 10:47 | 显示全部楼层
尽量不要在定时器中断中进行任何运算,所有的处理都在主程序中处理,可能处理速度会慢一点,因为会被定时器打断以下是我学习板上写的,手头上没有STC8H单片机,用8A的试了一下,你自己用示波器看一下
#include "Stc8a.h"
bit PWM_H;                        //标志PWM的高电平
unsigned int Duty;                        //高电平时间
unsigned char PWM_TIME_H_L;//PWM高电平时间的低位
unsigned char PWM_TIME_H_H;//PWM高电平时间的高位
unsigned char PWM_TIME_L_L;//PWM低电平时间的低位
unsigned char PWM_TIME_L_H;//PWM高电平时间的高位
sbit OUT=P0^0;
void main()
{
    P0M0=0XFF;
        P0=0X00;
        PWM_H=0;                        //PWM默认低电平时间
        Duty=10;                         //占空比设定
        AUXR |= 0x80;                //定时器时钟1T模式
        TMOD = 0x01;                //设置定时器模式:不自动重载
        TL0 = (65535-Duty)%256;                //设置定时初始值
        TH0 = (65535-Duty)/256;                //设置定时初始值
        TF0 = 0;                //清除TF0标志
        TR0 = 1;                //定时器0开始计时
        ET0=1;
    EA = 1;
    while (1)
        {
                PWM_TIME_H_L=(65535-Duty)%256;
                PWM_TIME_H_H=(65535-Duty)/256;
                PWM_TIME_L_L=(65535-50000+Duty)%256;        //设置定时初始值,50000为PWM整个周期的时间
                PWM_TIME_L_H=(65535-50000+Duty)/256;
        }

}
//===========================================================
void TM0_Isr() interrupt 1                                      
{                                                     
     if(PWM_H)
                 {
                         PWM_H=0;
                        OUT=1;       
                        TL0 = PWM_TIME_H_L;                //设置定时初始值
                        TH0 = PWM_TIME_H_H;                //设置定时初始值
                 }
        else
                 {
                         PWM_H=1;
                        OUT=0;       
                        TL0 =PWM_TIME_L_L;                //设置定时初始值
                        TH0 =PWM_TIME_L_H;                //设置定时初始值
                 }                
        TR0 = 1;                                 
}


回复

使用道具 举报

ID:624769 发表于 2021-10-20 13:21 来自手机 | 显示全部楼层
24m的晶振,1us就是24个时钟,0.5us就是12个时钟,去掉进入中断3个时钟,退出中断reti又3个时钟,那么如果你中断里面的程序达到6个时钟,那么你的程序就待在中断里不用出来了,而粗看你的代码,就算全是一个时钟,也远超6个时钟了,所以,只要你的中断策略不变,你这程序就没法正常跑起来。
回复

使用道具 举报

ID:734017 发表于 2021-10-20 23:37 | 显示全部楼层
188610329 发表于 2021-10-20 13:21
24m的晶振,1us就是24个时钟,0.5us就是12个时钟,去掉进入中断3个时钟,退出中断reti又3个时钟,那么如果 ...

感谢,现在对时钟上的认识还不够,谢谢指导
回复

使用道具 举报

ID:734017 发表于 2021-10-20 23:40 | 显示全部楼层
Y_G_G 发表于 2021-10-20 10:47
尽量不要在定时器中断中进行任何运算,所有的处理都在主程序中处理,可能处理速度会慢一点,因为会被定时器打 ...

感谢大哥,这几天比较忙,回家都半晚了,抽时间弄弄,这个写法好,在不进入中断时候,不响影其它操作,留给其它指令时间就多了。谢谢你
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表