搜索
bottom↓
回复: 17

请教个LPC1768 SYSTICK 延时的问题。看原子STM32用的SYSTICK延时。

[复制链接]

出0入0汤圆

发表于 2012-7-2 08:43:57 | 显示全部楼层 |阅读模式
下面是原子的例程。。。

#include <stm32f10x_lib.h>
#include "delay.h"
//////////////////////////////////////////////////////////////////////////////////         
//本程序只供学习使用,未经作者许可,不得用于其它任何用途
//Mini STM32开发板
//使用SysTick的普通计数模式对延迟进行管理
//包括delay_us,delay_ms
//正点原子@ALIENTEK
//技术论坛:www.openedv.com
//修改日期:2010/5/27
//版本:V1.2
//版权所有,盗版必究。
//Copyright(C) 正点原子 2009-2019
//All rights reserved
//********************************************************************************
//V1.2修改说明
//修正了中断中调用出现死循环的错误
//防止延时不准确,采用do while结构!
//////////////////////////////////////////////////////////////////////////////////         
static u8  fac_us=0;//us延时倍乘数
static u16 fac_ms=0;//ms延时倍乘数
//初始化延迟函数
//SYSTICK的时钟固定为HCLK时钟的1/8
//SYSCLK:系统时钟
void delay_init(u8 SYSCLK)
{
        SysTick->CTRL&=0xfffffffb;//bit2清空,选择外部时钟  HCLK/8
        fac_us=SYSCLK/8;                    
        fac_ms=(u16)fac_us*1000;
}                                                                    
//延时nms
//注意nms的范围
//SysTick->LOAD为24位寄存器,所以,最大延时为:
//nms<=0xffffff*8*1000/SYSCLK
//SYSCLK单位为Hz,nms单位为ms
//对72M条件下,nms<=1864
void delay_ms(u16 nms)
{                                     
        u32 temp;                  
        SysTick->LOAD=(u32)nms*fac_ms;//时间加载(SysTick->LOAD为24bit)
        SysTick->VAL =0x00;           //清空计数器
        SysTick->CTRL=0x01 ;          //开始倒数  
        do
        {
                temp=SysTick->CTRL;
        }
        while(temp&0x01&&!(temp&(1<<16)));//等待时间到达   
        SysTick->CTRL=0x00;       //关闭计数器
        SysTick->VAL =0X00;       //清空计数器                      
}   
//延时nus
//nus为要延时的us数.                                                                                      
void delay_us(u32 nus)
{               
        u32 temp;                     
        SysTick->LOAD=nus*fac_us; //时间加载                           
        SysTick->VAL=0x00;        //清空计数器
        SysTick->CTRL=0x01 ;      //开始倒数          
        do
        {
                temp=SysTick->CTRL;
        }
        while(temp&0x01&&!(temp&(1<<16)));//等待时间到达   
        SysTick->CTRL=0x00;       //关闭计数器
        SysTick->VAL =0X00;       //清空计数器         
}
///////////////////////////////////////////////////////////////////////////////////////////////
在LPC1768修改为SysTick->CTRL&=0xfffffffd;//中断禁止。。。。
fac_us=SYSCLK;       


在程序中初始化delay_init(96);

使用:delay_ms(500);

程序停止,中断发现
while(temp&0x01&&!(temp&(1<<16)));//等待时间到达  
temp的16位始终为零,也就是SysTick->CTRL的16位。
有用LPC1768帮忙试试,谢谢。

阿莫论坛20周年了!感谢大家的支持与爱护!!

一只鸟敢站在脆弱的枝条上歇脚,它依仗的不是枝条不会断,而是自己有翅膀,会飞。

出0入0汤圆

发表于 2012-7-3 02:05:55 | 显示全部楼层
楼主啊,直接调用CM3里面的SysTick_Config()就可以了啊~

出0入0汤圆

 楼主| 发表于 2012-7-3 08:14:50 | 显示全部楼层
SysTick->CTRL|=0x05 ;

可以了。
我想用延时的,不用中断。

谢谢楼上。

出0入0汤圆

发表于 2012-7-3 11:26:57 | 显示全部楼层
高手,学习了!

出0入0汤圆

发表于 2012-8-9 22:52:26 | 显示全部楼层
你好,我也在用lpc1768的systick延时,程序不成功.
有些疑问首先lpc1768 sysytick不能使用外部时钟,只能是内核时钟.内核时钟100Mhz,延时最多168ms,
其次我的程序也是死在了
while(temp&0x01&&!(temp&(1<<16)));//等待时间到达
请问怎么解决,

出0入0汤圆

发表于 2012-8-9 23:43:24 | 显示全部楼层
还没有调通,楼主把代码发上来 看看吧

出0入0汤圆

 楼主| 发表于 2012-8-10 08:20:20 | 显示全部楼层
调通了。

出0入0汤圆

 楼主| 发表于 2012-8-10 08:20:49 | 显示全部楼层
看蓝色字。。。。

出0入0汤圆

发表于 2012-8-10 12:25:24 | 显示全部楼层
已经能延时了,但是延时不准确,快很多.看看程序哪里有问题.

出0入0汤圆

发表于 2012-8-10 12:35:09 | 显示全部楼层
延时大约快3倍

出0入0汤圆

发表于 2012-8-10 13:50:47 | 显示全部楼层
#include <lpc17xx.h>
#include "delay.h"
//////////////////////////////////////////////////////////////////////////////////         
//本程序只供学习使用,未经作者许可,不得用于其它任何用途
//Mini STM32开发板
//使用SysTick的普通计数模式对延迟进行管理
//包括delay_us,delay_ms
//正点原子@ALIENTEK
//技术论坛:www.openedv.com
//修改日期:2010/5/27
//版本:V1.2
//版权所有,盗版必究。
//Copyright(C) 正点原子 2009-2019
//All rights reserved
//********************************************************************************
//V1.2修改说明
//修正了中断中调用出现死循环的错误
//防止延时不准确,采用do while结构!
//////////////////////////////////////////////////////////////////////////////////         
static uint8_t  fac_us=0;//us延时倍乘数
static uint16_t fac_ms=0;//ms延时倍乘数
//初始化延迟函数
//SYSTICK的时钟固定为HCLK时钟的1/8
//SYSCLK:系统时钟
void delay_init(uint8_t SYSCLK)
{
        //SysTick->CTRL&=0xfffffffd;//bit2清空,选择外部时钟  HCLK/8
        fac_us=SYSCLK;                    
        fac_ms=(uint16_t)fac_us*1000;
}                                                                    
//延时nms
//注意nms的范围
//SysTick->LOAD为24位寄存器,所以,最大延时为:
//nms<=0xffffff*8*1000/SYSCLK
//SYSCLK单位为Hz,nms单位为ms
//对72M条件下,nms<=1864
void delay_ms(uint16_t nms)
{                                     
        uint32_t temp;
                  
        SysTick->LOAD=(uint32_t)fac_ms;//时间加载(SysTick->LOAD为24bit)
        SysTick->VAL =0x00;           //清空计数器
        SysTick->CTRL=0x05 ;          //开始倒数
        while(nms--)
        {
        do
        {
                temp=SysTick->CTRL;
        }
        while(temp&0x01&&!(temp&(1<<16)));//等待时间到达
        SysTick->LOAD=(uint32_t)fac_ms;//时间加载(SysTick->LOAD为24bit)
        SysTick->VAL =0x00;           //清空计数器
        }   
        SysTick->CTRL=0x00;       //关闭计数器
        SysTick->VAL =0X00;       //清空计数器                      
}   
//延时nus
//nus为要延时的us数.                                                                                      
void delay_us(uint16_t nus)
{               
        uint32_t temp;                     
        SysTick->LOAD=nus*fac_us; //时间加载                           
        SysTick->VAL=0x00;        //清空计数器
        SysTick->CTRL=0x05 ;      //开始倒数          
        do
        {
                temp=SysTick->CTRL;
        }
        while(temp&0x01&&!(temp&(1<<16)));//等待时间到达   
        SysTick->CTRL=0x00;       //关闭计数器
        SysTick->VAL =0X00;       //清空计数器         
}

我的程序延时很不准确,大概快3倍,什么问题

出0入0汤圆

 楼主| 发表于 2012-8-10 15:22:09 | 显示全部楼层
倍频到96MHz吗?
我用没问题。
没详细测试。

要不用中断的。
SysTick_Config(SystemCoreClock/1000);////1ms
void SysTick_Handler (void)
{
               
               

                Timer0_1sCount++;
}

出0入0汤圆

发表于 2012-8-10 15:52:20 | 显示全部楼层
我外部晶振12M,调用系统初始化SystemInit();  ,这样的话系统时钟是100M么.          用中断的效果很好.定时没有变快

出0入0汤圆

发表于 2012-8-10 16:57:24 | 显示全部楼层
找到原因了,fac_ms是16位的.而延时1ms的值是l100000,溢出了. 利用位带实现io口位操作你实现没有?我打算接下来搞这个.加我qq316323958

出0入0汤圆

发表于 2012-9-15 11:59:51 | 显示全部楼层
STM32系统时钟72M,晶振8M,delay_init(72),怎么我使用了 delay_us延时输出高低电平(20us以下的试验),我用示波器看了,延时不准确,误差还是比较大的

出0入0汤圆

 楼主| 发表于 2013-4-9 10:07:17 | 显示全部楼层
spydf 发表于 2012-8-10 16:57
找到原因了,fac_ms是16位的.而延时1ms的值是l100000,溢出了. 利用位带实现io口位操作你实现没有?我打算接下 ...

/* The processor memory map includes two bit-band regions. These occupy the lowest
* 1MB of the SRAM and peripheral memory regions respectively.
* + SRAM:         Bit-band region:         0x20000000 - 0x20100000
*                         Bit-band alias:                0x22000000 - 0x23FFFFFF
* + PERI:        Bit-band region:        0x40000000 - 0x40100000
*                         Bit-band alias:                0x42000000 - 0x43FFFFFF
* The mapping formula:
*                 bit_word_offset = (byte_offset * 32) + (bit_number * 4)
*                 bit_word_address = bit_band_base + bit_word_offset
* where:
*         + bit_word_offset: the position of the target bit in the bit-band memory region
*         + bit_word_addr: the address of the word in the alias memory region that maps to the target bit
*  + bit_band_base: the starting address of the alias region
*  + byte_offset: the number of byte in the bit-band region that contains the targeted bit
*  + bit_number: is the bit position (0-7) of the targeted bit
*
* Note: The fact, the SRAM on LPC1768 just available in two ranges:
*  + 0x2007C000 - 0x2007FFFF: for SRAM - bank 0
*  + 0x20080000 - 0x20083FFF: for SRAM - bank 1
*  (And one range for GPIO peripheral but assigned in SRAM ranges: 0x2009C000 - 0x2009FFFF)
*/

/* Bit band SRAM definitions */
#define BITBAND_SRAM_REF   0x20000000
#define BITBAND_SRAM_BASE  0x22000000
#define BITBAND_SRAM(a,b) ((BITBAND_SRAM_BASE + ((a-BITBAND_SRAM_REF)<<5) + (b<<2)))  // Convert SRAM address
/* Bit band PERIPHERAL definitions */
#define BITBAND_PERI_REF   0x40000000
#define BITBAND_PERI_BASE  0x42000000
#define BITBAND_PERI(a,b) ((BITBAND_PERI_BASE + ((a-BITBAND_PERI_REF)<<5) + (b<<2)))  // Convert PERI address
/* Basic bit band function definitions */
#define BITBAND_SRAM_ClearBit(a,b)        (*(volatile uint32_t *) (BITBAND_SRAM(a,b)) = 0)
#define BITBAND_SRAM_SetBit(a,b)                (*(volatile uint32_t *) (BITBAND_SRAM(a,b)) = 1)
#define BITBAND_SRAM_GetBit(a,b)                (*(volatile uint32_t *) (BITBAND_SRAM(a,b)))

#define BITBAND_PERI_ClearBit(a,b)        (*(volatile uint32_t *) (BITBAND_PERI(a,b)) = 0)
#define BITBAND_PERI_SetBit(a,b)                (*(volatile uint32_t *) (BITBAND_PERI(a,b)) = 1)
#define BITBAND_PERI_GetBit(a,b)                (*(volatile uint32_t *) (BITBAND_PERI(a,b)))

//volatile unsigned long bbVarAry[7] __attribute__(( at(0x20003014) ));
//volatile unsigned long* const pbbaVar= (void*)(0x22000000+0x3014*8*4);


//位带操作,实现51类似的GPIO控制功能
//具体实现思想,参考<<CM3权威指南>>第五章(87页~92页).
//IO口操作宏定义

//0x2000_0000-0x200F_FFFF(SRAM区中的最低1MB)
//对于SRAM位带区的某个比特,记它所在字节地址为A,位序号为n(0<=n<=7),则该比特在别名区的地址为:
//AliasAddr= 0x22000000+((A-0x20000000)*8+n)*4 =0x22000000+ (A-0x20000000)*32 + n*4
//0x4000_0000-0x400F_FFFF(片上外设区中的最低1MB)
//对于片上外设位带区的某个比特,记它所在字节的地址为A,位序号为n(0<=n<=7),则该比特在别名区的地址为:
//AliasAddr= 0x42000000+((A-0x40000000)*8+n)*4 =0x42000000+ (A-0x40000000)*32 + n*4

#define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x2000000+((addr &0xFFFFF)<<5)+(bitnum<<2))
#define MEM_ADDR(addr)  *((volatile unsigned long  *)(addr))
#define BIT_ADDR(addr, bitnum)   MEM_ADDR(BITBAND(addr, bitnum))
//IO口地址映射
//FIODIR
#define LPC_GPIO0_DIR_Addr    (0x2009c000) //
#define LPC_GPIO1_DIR_Addr    (0x2009c020) //
#define LPC_GPIO2_DIR_Addr    (0x2009c040) //
#define LPC_GPIO3_DIR_Addr    (0x2009c060) //
#define LPC_GPIO4_DIR_Addr    (0x2009c080) //
//FIOMASK
#define LPC_GPIO0_MASK_Addr    (0x2009c010) //
#define LPC_GPIO1_MASK_Addr    (0x2009c030) //
#define LPC_GPIO2_MASK_Addr    (0x2009c050) //
#define LPC_GPIO3_MASK_Addr    (0x2009c070) //
#define LPC_GPIO4_MASK_Addr    (0x2009c090) //
//FIOPIN
#define LPC_GPIO0_PIN_Addr    (0x2009c014) //
#define LPC_GPIO1_PIN_Addr    (0x2009c034) //
#define LPC_GPIO2_PIN_Addr    (0x2009c054) //
#define LPC_GPIO3_PIN_Addr    (0x2009c074) //
#define LPC_GPIO4_PIN_Addr    (0x2009c094) //
//FIOSET
#define LPC_GPIO0_SET_Addr    (0x2009c018) //
#define LPC_GPIO1_SET_Addr    (0x2009c038) //
#define LPC_GPIO2_SET_Addr    (0x2009c058) //
#define LPC_GPIO3_SET_Addr    (0x2009c078) //
#define LPC_GPIO4_SET_Addr    (0x2009c098) //
//FIOCLR
#define LPC_GPIO0_CLR_Addr    (0x2009c01C) //
#define LPC_GPIO1_CLR_Addr    (0x2009c03C) //
#define LPC_GPIO2_CLR_Addr    (0x2009c05C) //
#define LPC_GPIO3_CLR_Addr    (0x2009c07C) //
#define LPC_GPIO4_CLR_Addr    (0x2009c09C) //
///================================================
//FIODIR
#define P0DIR(n)    BIT_ADDR(LPC_GPIO0_DIR_Addr,n)   
#define P1DIR(n)    BIT_ADDR(LPC_GPIO1_DIR_Addr,n)  
#define P2DIR(n)    BIT_ADDR(LPC_GPIO2_DIR_Addr,n)  
#define P3DIR(n)    BIT_ADDR(LPC_GPIO3_DIR_Addr,n)  
#define P4DIR(n)    BIT_ADDR(LPC_GPIO4_DIR_Addr,n)  
//FIOMASK
#define P0MASK(n)    BIT_ADDR(LPC_GPIO0_MASK_Addr,n)   
#define P1MASK(n)    BIT_ADDR(LPC_GPIO1_MASK_Addr,n)  
#define P2MASK(n)    BIT_ADDR(LPC_GPIO2_MASK_Addr,n)  
#define P3MASK(n)    BIT_ADDR(LPC_GPIO3_MASK_Addr,n)  
#define P4MASK(n)    BIT_ADDR(LPC_GPIO4_MASK_Addr,n)
//FIOPIN
#define P0PIN(n)    BIT_ADDR(LPC_GPIO0_PIN_Addr,n)   
#define P1PIN(n)    BIT_ADDR(LPC_GPIO1_PIN_Addr,n)  
#define P2PIN(n)    BIT_ADDR(LPC_GPIO2_PIN_Addr,n)  
#define P3PIN(n)    BIT_ADDR(LPC_GPIO3_PIN_Addr,n)  
#define P4PIN(n)    BIT_ADDR(LPC_GPIO4_PIN_Addr,n)
//FIOSET
#define P0SET(n)    BIT_ADDR(LPC_GPIO0_SET_Addr,n)   
#define P1SET(n)    BIT_ADDR(LPC_GPIO1_SET_Addr,n)  
#define P2SET(n)    BIT_ADDR(LPC_GPIO2_SET_Addr,n)  
#define P3SET(n)    BIT_ADDR(LPC_GPIO3_SET_Addr,n)  
#define P4SET(n)    BIT_ADDR(LPC_GPIO4_SET_Addr,n)
//FIOCLR
#define P0CLR(n)    BIT_ADDR(LPC_GPIO0_CLR_Addr,n)   
#define P1CLR(n)    BIT_ADDR(LPC_GPIO1_CLR_Addr,n)  
#define P2CLR(n)    BIT_ADDR(LPC_GPIO2_CLR_Addr,n)  
#define P3CLR(n)    BIT_ADDR(LPC_GPIO3_CLR_Addr,n)  
#define P4CLR(n)    BIT_ADDR(LPC_GPIO4_CLR_Addr,n)

出0入0汤圆

 楼主| 发表于 2013-4-9 10:27:25 | 显示全部楼层
是个短延时,100多毫秒的延时,长了不行。

要想长延时,就多加几个delay_ms();

出0入0汤圆

发表于 2014-2-7 21:23:58 | 显示全部楼层
spydf 发表于 2012-8-10 16:57
找到原因了,fac_ms是16位的.而延时1ms的值是l100000,溢出了. 利用位带实现io口位操作你实现没有?我打算接下 ...

学习了
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-3-29 10:39

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

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