OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 13026|回复: 21

stm32f103指令执行速度真的是1.25DMIPS/MHz?

[复制链接]

1

主题

8

帖子

0

精华

新手上路

积分
31
金钱
31
注册时间
2018-2-10
在线时间
10 小时
发表于 2018-2-10 22:59:27 | 显示全部楼层 |阅读模式
1金钱
本帖最后由 qiaoqiao001 于 2018-2-10 23:01 编辑

主频设置为56M
ADC设置为4分频14M
采样周期设置为ADC_SampleTime_1Cycles5,手册说是1us

不管是中断方式还是在主循环查询中断标志,清除标志后只能执行1条指令就又再次中断

1us的时间只能执行几个指令?

如果按官方的算法,平均每指令周期=1000000000ns/(56000000*1.25)=14.28ns
1us大约能执行70条执行
慢了10倍。。。。。

两种方式的代码贴出来,各位大神给看看验证一下,是我配置错误还是就这么慢

PC15接了个LED灯
注释掉:ADC_ConversionValue = (uint16_t)ADC1->DR;灯就灭了
不注释灯是亮的

中断方式:
[mw_shl_code=c,true]#include "stm32f10x.h"

uint16_t ADC_ConversionValue=0;
uint16_t ADC_num=0;

void ADC1_init(void)
{
  NVIC_InitTypeDef NVIC_InitStructure;
  GPIO_InitTypeDef GPIO_InitStructure;
  ADC_InitTypeDef ADC_InitStructure;
  
  /*配置ADC时钟,为PCLK2的4分频,即56/4=14MHz,ADC1在APB2上为56M*/
  RCC_ADCCLKConfig(RCC_PCLK2_Div4);
  
  /* Enable ADC1 and GPIOC clock */
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOC, ENABLE);
  
  //中断优先级NVIC设置
  NVIC_InitStructure.NVIC_IRQChannel = ADC1_2_IRQn;  //ADC1_2中断
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;  //先占优先级0级
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;  //从优先级0级
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
  NVIC_Init(&NVIC_InitStructure);  //初始化NVIC寄存器

  /* Configure PC.01  as analog input */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
  GPIO_Init(GPIOC, &GPIO_InitStructure);// PC1,输入时不用设置速率
  
  /* ADC1 configuration */        
  ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;//独立ADC模式
  ADC_InitStructure.ADC_ScanConvMode = DISABLE;//禁止扫描模式,扫描模式用于多通道采集
  ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;//开启连续转换模式,即不停地进行ADC转换
  ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;//不使用外部触发转换
  ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;//采集数据右对齐
  ADC_InitStructure.ADC_NbrOfChannel = 1;//要转换的通道数目1
  ADC_Init(ADC1, &ADC_InitStructure);
  
  /*配置ADC1的通道11为1.5个采样周期共14个周期1.17us,序列为1 */
  ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 1, ADC_SampleTime_1Cycles5);
  //ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 1, ADC_SampleTime_7Cycles5);
  //ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 1, ADC_SampleTime_13Cycles5);
  //ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 1, ADC_SampleTime_28Cycles5);
  //ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 1, ADC_SampleTime_41Cycles5);
  //ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 1, ADC_SampleTime_239Cycles5);
  
  /* Enable EOC interrupt */
  ADC_ITConfig(ADC1, ADC_IT_EOC, ENABLE);

  /* Enable ADC1 */
  ADC_Cmd(ADC1, ENABLE);
  
  /*复位校准寄存器 */   
  ADC_ResetCalibration(ADC1);
  /*等待校准寄存器复位完成 */
  while(ADC_GetResetCalibrationStatus(ADC1));
  
  /* ADC校准 */
  ADC_StartCalibration(ADC1);
  /* 等待校准完成*/
  while(ADC_GetCalibrationStatus(ADC1));
  
  /* 由于没有采用外部触发,所以使用软件触发ADC转换 */
  ADC_SoftwareStartConvCmd(ADC1, ENABLE);
}


int main(void)
{

  GPIO_InitTypeDef GPIO_Initstructure;

  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);
  GPIO_Initstructure.GPIO_Pin=GPIO_Pin_15;//PC15
  GPIO_Initstructure.GPIO_Mode=GPIO_Mode_Out_PP; //普通推挽输出
  GPIO_Initstructure.GPIO_Speed=GPIO_Speed_50MHz;
  GPIO_Init(GPIOC,&GPIO_Initstructure);//最后初始化
  GPIOC->BRR = GPIO_Pin_15;
        
  ADC1_init();
  
  
  while (1)
  {
    ADC_num++;
    ADC_num--;
  }
}

//ADC1_2中断服务程序
void ADC1_2_IRQHandler(void)
{
    if(ADC1->SR & ADC_FLAG_EOC)  //检查ADC1EOC中断发生与否
    {
      ADC1->SR = ~(uint32_t)ADC_FLAG_EOC;  //操作寄存器清除ADC1EOC中断标志
      
      ADC_ConversionValue = (uint16_t)ADC1->DR;
      
      if(ADC1->SR & ADC_FLAG_EOC)
      {
        GPIOC->BSRR = GPIO_Pin_15;
      }
      else
      {
        GPIOC->BRR = GPIO_Pin_15;
      }
    }
}[/mw_shl_code]



主循环查询方式:
[mw_shl_code=c,true]#include "stm32f10x.h"

uint16_t ADC_ConversionValue=0;

void ADC1_init(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;
  ADC_InitTypeDef ADC_InitStructure;
  
  /*配置ADC时钟,为PCLK2的4分频,即56/4=14MHz,ADC1在APB2上为56M*/
  RCC_ADCCLKConfig(RCC_PCLK2_Div4);
  
  /* Enable ADC1 and GPIOC clock */
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOC, ENABLE);
  
  /* Configure PC.01  as analog input */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
  GPIO_Init(GPIOC, &GPIO_InitStructure);// PC1,输入时不用设置速率
  
  /* ADC1 configuration */        
  ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;//独立ADC模式
  ADC_InitStructure.ADC_ScanConvMode = DISABLE;//禁止扫描模式,扫描模式用于多通道采集
  ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;//开启连续转换模式,即不停地进行ADC转换
  ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;//不使用外部触发转换
  ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;//采集数据右对齐
  ADC_InitStructure.ADC_NbrOfChannel = 1;//要转换的通道数目1
  ADC_Init(ADC1, &ADC_InitStructure);
  
  /*配置ADC1的通道11为1.5个采样周期共14个周期1.17us,序列为1 */
  ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 1, ADC_SampleTime_1Cycles5);
  //ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 1, ADC_SampleTime_7Cycles5);
  //ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 1, ADC_SampleTime_13Cycles5);
  //ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 1, ADC_SampleTime_28Cycles5);
  //ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 1, ADC_SampleTime_41Cycles5);
  //ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 1, ADC_SampleTime_239Cycles5);
  
  /* Enable ADC1 */
  ADC_Cmd(ADC1, ENABLE);
  
  /*复位校准寄存器 */   
  ADC_ResetCalibration(ADC1);
  /*等待校准寄存器复位完成 */
  while(ADC_GetResetCalibrationStatus(ADC1));
  
  /* ADC校准 */
  ADC_StartCalibration(ADC1);
  /* 等待校准完成*/
  while(ADC_GetCalibrationStatus(ADC1));
  
  /* 由于没有采用外部触发,所以使用软件触发ADC转换 */
  ADC_SoftwareStartConvCmd(ADC1, ENABLE);
}


int main(void)
{

  GPIO_InitTypeDef GPIO_Initstructure;
  
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);
  GPIO_Initstructure.GPIO_Pin=GPIO_Pin_15;//PC15
  GPIO_Initstructure.GPIO_Mode=GPIO_Mode_Out_PP; //普通推挽输出
  GPIO_Initstructure.GPIO_Speed=GPIO_Speed_50MHz;
  GPIO_Init(GPIOC,&GPIO_Initstructure);//最后初始化
  GPIOC->BRR = GPIO_Pin_15;
        
  ADC1_init();
  
  
  while (1)
  {
    if(ADC1->SR & ADC_FLAG_EOC)  //检查ADC1EOC中断发生与否
    {
      ADC1->SR = ~(uint32_t)ADC_FLAG_EOC;  //操作寄存器清除ADC1EOC中断标志
      
      ADC_ConversionValue = (uint16_t)ADC1->DR;
      
      if(ADC1->SR & ADC_FLAG_EOC)
      {
        GPIOC->BSRR = GPIO_Pin_15;
      }
      else
      {
        GPIOC->BRR = GPIO_Pin_15;
      }
    }
  }
}
[/mw_shl_code]

最佳答案

查看完整内容[请看2#楼]

CPU执行中断时需要时间的,入栈,出栈,以及其他处理,都需要时间! STM32的中断性能,不超过500Khz,也就是当你的中断速度达到2us一次的时候,基本上CPU就不要干其他什么事情了(不管你中断函数多精简),所以你的验证方法,是不可取的。 官方说的1.25DMIPS/MHz,是通过测试一些算法来实现的,而不是测试中断服务速度。
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165524
金钱
165524
注册时间
2010-12-1
在线时间
2116 小时
发表于 2018-2-10 22:59:28 | 显示全部楼层
CPU执行中断时需要时间的,入栈,出栈,以及其他处理,都需要时间!
STM32的中断性能,不超过500Khz,也就是当你的中断速度达到2us一次的时候,基本上CPU就不要干其他什么事情了(不管你中断函数多精简),所以你的验证方法,是不可取的。
官方说的1.25DMIPS/MHz,是通过测试一些算法来实现的,而不是测试中断服务速度。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复

使用道具 举报

1

主题

8

帖子

0

精华

新手上路

积分
31
金钱
31
注册时间
2018-2-10
在线时间
10 小时
 楼主| 发表于 2018-2-11 10:34:47 | 显示全部楼层
没人给验证一下吗?版主帮帮忙,我是不是哪里错了?
回复

使用道具 举报

1

主题

8

帖子

0

精华

新手上路

积分
31
金钱
31
注册时间
2018-2-10
在线时间
10 小时
 楼主| 发表于 2018-2-11 23:14:16 | 显示全部楼层
用的IAR,觉得是IAR的问题,学习原子版主的教程装上keil,结果一样,还是1us只能执行几个指令。。。。
回复

使用道具 举报

4

主题

144

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
345
金钱
345
注册时间
2017-1-18
在线时间
80 小时
发表于 2018-2-12 09:27:03 | 显示全部楼层
外设的速度和CPU的速度是2回事儿。
回复

使用道具 举报

1

主题

8

帖子

0

精华

新手上路

积分
31
金钱
31
注册时间
2018-2-10
在线时间
10 小时
 楼主| 发表于 2018-2-12 11:48:02 | 显示全部楼层
时钟系统图里的SYSCLK难道不是CPU的时钟?PLL在SYSCLK之前,如果倍频只是给外设用指令速度没有提升,在实时性的应用中只能当外部时钟的速度用。。。。是这样吗?
回复

使用道具 举报

4

主题

144

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
345
金钱
345
注册时间
2017-1-18
在线时间
80 小时
发表于 2018-2-12 12:24:13 | 显示全部楼层
中断标志清除有问题。ADC1->SR = ~(uint32_t)ADC_FLAG_EOC;  //操作寄存器清除ADC1EOC中断标志。这样写SR的其它标志位不是都变了吗?
回复

使用道具 举报

1

主题

8

帖子

0

精华

新手上路

积分
31
金钱
31
注册时间
2018-2-10
在线时间
10 小时
 楼主| 发表于 2018-2-12 13:14:02 | 显示全部楼层
看手册ADC状态寄存器(ADC_SR) ,状态位下边w0
忘了在哪看到“这个寄存器写1无效写0清零”,好像是原子版主的某个教程
官方库清标志函数:
[mw_shl_code=c,true]void ADC_ClearFlag(ADC_TypeDef* ADCx, uint8_t ADC_FLAG)
{
  /* Check the parameters */
  assert_param(IS_ADC_ALL_PERIPH(ADCx));
  assert_param(IS_ADC_CLEAR_FLAG(ADC_FLAG));
  /* Clear the selected ADC flags */
  ADCx->SR = ~(uint32_t)ADC_FLAG;
}[/mw_shl_code]

回复

使用道具 举报

4

主题

144

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
345
金钱
345
注册时间
2017-1-18
在线时间
80 小时
发表于 2018-2-12 13:26:35 | 显示全部楼层
认真看一下手册SR寄存器说明就明白了。这个子程序是清除所有标志,和你的不一样。再有你的程序直接屏蔽ADC1->SR = ~(uint32_t)ADC_FLAG_EOC; 就应该行了。
回复

使用道具 举报

1

主题

8

帖子

0

精华

新手上路

积分
31
金钱
31
注册时间
2018-2-10
在线时间
10 小时
 楼主| 发表于 2018-2-12 13:49:57 | 显示全部楼层
看手册第24页的表,read / clear (rc_w0) 软件可以读此位,也可以通过写’0’清除此位,写’1’对此位无影响。
如果这个清除函数是全部清除,第2个参数又有什么意义?

如果屏蔽ADC1->SR = ~(uint32_t)ADC_FLAG_EOC;,就是不清除中断标志,那就是会一直进中断程序,灯始终是亮的,不会灭
回复

使用道具 举报

4

主题

144

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
345
金钱
345
注册时间
2017-1-18
在线时间
80 小时
发表于 2018-2-12 23:00:29 | 显示全部楼层
如果你好好看手册就没有这样的问题了。再有你试过吗?
回复

使用道具 举报

6

主题

462

帖子

0

精华

高级会员

Rank: 4

积分
906
金钱
906
注册时间
2017-12-15
在线时间
111 小时
发表于 2018-2-12 23:06:51 | 显示全部楼层
xdzhang 发表于 2018-2-12 13:26
认真看一下手册SR寄存器说明就明白了。这个子程序是清除所有标志,和你的不一样。再有你的程序直接屏蔽ADC1 ...

你看清楚再说话。

如果你好好看手册就没有这样的问题了。再有你试过吗?
回复

使用道具 举报

6

主题

462

帖子

0

精华

高级会员

Rank: 4

积分
906
金钱
906
注册时间
2017-12-15
在线时间
111 小时
发表于 2018-2-12 23:08:57 | 显示全部楼层
你理解中的"一条指令"是什么意思??
回复

使用道具 举报

4

主题

144

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
345
金钱
345
注册时间
2017-1-18
在线时间
80 小时
发表于 2018-2-12 23:09:34 | 显示全部楼层
1,SR寄存器有其它标志,你不能全部清零。2,读ADC数据自然清除ADC_FLAG_EOC标志。看明白了吗?
回复

使用道具 举报

4

主题

144

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
345
金钱
345
注册时间
2017-1-18
在线时间
80 小时
发表于 2018-2-12 23:15:43 | 显示全部楼层
a496298685 发表于 2018-2-12 23:06
你看清楚再说话。

如果你好好看手册就没有这样的问题了。再有你试过吗?

你看清楚问题了吗?
回复

使用道具 举报

6

主题

462

帖子

0

精华

高级会员

Rank: 4

积分
906
金钱
906
注册时间
2017-12-15
在线时间
111 小时
发表于 2018-2-12 23:23:32 | 显示全部楼层
xdzhang 发表于 2018-2-12 23:09
1,SR寄存器有其它标志,你不能全部清零。2,读ADC数据自然清除ADC_FLAG_EOC标志。看明白了吗?

网友你收敛一点。

TIM截图20180212232221.png
TIM截图20180212232243.png
回复

使用道具 举报

4

主题

144

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
345
金钱
345
注册时间
2017-1-18
在线时间
80 小时
发表于 2018-2-12 23:26:38 | 显示全部楼层
a496298685 发表于 2018-2-12 23:23
网友你收敛一点。

同样的话回送给你。
回复

使用道具 举报

4

主题

144

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
345
金钱
345
注册时间
2017-1-18
在线时间
80 小时
发表于 2018-2-12 23:47:12 | 显示全部楼层
[img]file:///C:\Documents and Settings\Administrator\Application Data\Tencent\Users\9937250\QQ\WinTemp\RichOle\3UC8[9FOO9S2GQIGCQ3LCP0.png[/img]

20180212234622.png
回复

使用道具 举报

4

主题

144

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
345
金钱
345
注册时间
2017-1-18
在线时间
80 小时
发表于 2018-2-13 00:08:03 | 显示全部楼层
另外程序中有一个问题:只执行GPIOC->BRR = GPIO_Pin_15;因为在 if(ADC1->SR & ADC_FLAG_EOC)  //检查ADC1EOC中断发生与否
    {
      ADC1->SR = ~(uint32_t)ADC_FLAG_EOC;之后
(ADC1->SR & ADC_FLAG_EOC)永远是假。
回复

使用道具 举报

4

主题

144

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
345
金钱
345
注册时间
2017-1-18
在线时间
80 小时
发表于 2018-2-13 00:10:47 | 显示全部楼层
if(ADC1->SR & ADC_FLAG_EOC)  //检查ADC1EOC中断发生与否
    {
      ADC1->SR = ~(uint32_t)ADC_FLAG_EOC;  //操作寄存器清除ADC1EOC中断标志
      
      ADC_ConversionValue = (uint16_t)ADC1->DR;
       之后
(ADC1->SR & ADC_FLAG_EOC)就是假。GPIOC->BSRR = GPIO_Pin_15;不会被执行。
回复

使用道具 举报

1

主题

8

帖子

0

精华

新手上路

积分
31
金钱
31
注册时间
2018-2-10
在线时间
10 小时
 楼主| 发表于 2018-2-13 03:39:08 | 显示全部楼层
二位冷静,读取清除也对,但是我提出的问题是指令执行速度没有达到主频的速度

PC15接了个LED灯
注释掉:ADC_ConversionValue = (uint16_t)ADC1->DR;   灯就灭了
不注释:ADC_ConversionValue = (uint16_t)ADC1->DR;   灯是亮的

注释与不注释仅仅是验证中断后能执行几条指令,点灯也是有个提示,将此句换成其他任何语句都是这样,增加多条也同样,拿ADC做实验也仅仅是实验,定时器同样存在执行速度不是主频的问题,首先是从定时器发现的,后来在ADC中也这样,就很纳闷,拿ADC的代码发上来了

我的问题是STM32F103的指令执行速度真的是1.25DMIPS/MHz吗?
回复

使用道具 举报

1

主题

8

帖子

0

精华

新手上路

积分
31
金钱
31
注册时间
2018-2-10
在线时间
10 小时
 楼主| 发表于 2018-2-13 03:53:45 | 显示全部楼层
将采集周期改成ADC_SampleTime_7Cycles5,灯就是灭的,因为时间长了,够执行完中断里的几句代码了

之所以不用官方库函数清除标志是因为库函数编译后代码比中断里的几句代码都多,也没有用读取DR的方式清除中断标志是因为中断开始清标志是习惯,还有总要做些判断才读取到想要的地方,或者累加,比较等等。

要验证的是56M的速度1us不能就执行这几条指令吧,数着指令的个数感觉是外部8M的速度。
回复

使用道具 举报

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

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-6-8 14:16

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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