水水水木木木 发表于 2025-9-3 10:43:05

ercircle 发表于 2025-9-3 10:41


没有用库。我用库试一下。

ercircle 发表于 2025-9-3 10:46:22

水水水木木木 发表于 2025-9-3 10:43
没有用库。我用库试一下。

官网下载最新版本:

https://www.stcaimcu.com/data/download/Library/STC8_MDU16.LIB

水水水木木木 发表于 2025-9-3 10:58:16

示例中少了下面的三个定义。
#define   MD1U16                  (*(unsigned intvolatile xdata *)0xfcf2)
#define   MD5U16                  (*(unsigned intvolatile xdata *)0xfcf4)
#define   MD3U32                  (*(unsigned long volatile xdata *)0xfcf0)
但是就算这样,实际用示波器测量,和软件直接算没区别。总中断函数执行时间是13us左右,去掉这个乘法是3.5us左右。也就是乘法用了10us左右。硬件和软件需要的时间是差不多的。
代码如下:
                        MD1U16 = SWING_HW;
                        MD5U16 = M_q15;
                        ARCON = 4 << 5;
                        OPCON = 1;      //启动硬件乘法器
                        while((OPCON & 1) != 0);
                        half_cmd = MD3U32 >> 15;
其中SWING_HW和M_q15都是uint16。实测确实是需要10us的时间。
我再用库试一下,看看咋样。

水水水木木木 发表于 2025-9-3 11:07:37

添加了MDU16的硬件库后,再执行这个代码,没效果啊。和软件算是一样的时间。
half_cmd = ((int32_t)SWING_HW * (uint16_t)M_q15) >> 15;
是不是因为运算过程中保留了32位的数据长度,而标准的运算是16*16只保留16位的长度?
上面这个运算,应该是32位*16位,所以没用调用内部的硬件乘法?那如果我想保留16*16的结果,不要截断为16位。应该怎么操作呢?
上面这种运算需要的时间比用寄存器操作慢1us左右。实测是15us左右。
如果16*16位变量运算的话,运算结果溢出就被截断了。正常做法就是添加uint32,表示按照32位长度保存结果。那是不是就不会触发内部硬件MDU16乘法操作了?还是说需要其他配置?

水水水木木木 发表于 2025-9-3 11:20:15

ercircle 发表于 2025-9-3 10:46
官网下载最新版本:

https://www.stcaimcu.com/data/download/Library/STC8_MDU16.LIB

实测了。还是10us多。可能是因为需要保留32位数据长度导致没有使用硬件乘法。比寄存器操作还慢1us。是不是要换成AI8051U?或者您有时间也可以测试一下,直接用这个语句测试就行。

水水水木木木 发表于 2025-9-3 11:36:33

ercircle 发表于 2025-9-3 10:46
官网下载最新版本:

https://www.stcaimcu.com/data/download/Library/STC8_MDU16.LIB

我将int32去掉了,实测是4.5us。确实快了很多。代码如下。
half_cmd = (SWING_HW * M_q15) >> 15;
我再将int32加上看看。下面这个语句的执行时间就是15us左右。这里的时间是我整个中断的时间,还有其他语句。单独这个语句的时间应该在10us左右。上面16*16位运算单语句估计只要1us左右。16*16速度快很多。这是添加了硬件库后的结果。
half_cmd = ((int32_t)SWING_HW * M_q15) >> 15;

ercircle 发表于 2025-9-3 11:36:54

水水水木木木 发表于 2025-9-3 11:20
实测了。还是10us多。可能是因为需要保留32位数据长度导致没有使用硬件乘法。比寄存器操作还慢1us。是不 ...
我测试手册例程16位乘以16位取32位结果只需要3.75us@11.0592MHz,可以发下您的测试程序吗?


#include <STC8H.H>
#include <def.H>
#include <stdio.H>
void Delay10us(void)      //@11.0592MHz
{
      unsigned char data i;

      i = 35;
      while (--i);
}

void main()
{

////////////////////////////////////////////////////////////////////////////////
//16 位乘 16 位
////////////////////////////////////////////////////////////////////////////////
unsigned long res;
unsigned int dat1, dat2;
P_SW2 |= 0x80;

P2M1 = 0;   P2M0 = 0;   //设置为准双向口
P20 = 1;
Delay10us();
P20 = 0;
Delay10us();
P20 = 1;
//访问扩展寄存器 xsfr
MD1 = dat1;
//dat1 用户给定
MD5 = dat2;
//dat2 用户给定
ARCON = 4 << 5;
//16 位*16 位,乘法模式
OPCON = 1;
//启动计算
while((OPCON & 1) != 0);
//等待计算完成
res = MD3;
P20 = 0;
//32 位结果
//////////////////////////////////////////////////////////////////////////////////
////32 位除以 16 位
//////////////////////////////////////////////////////////////////////////////////
//unsigned long res;
//unsigned long dat1;
//unsigned int dat2;

////访问扩展寄存器 xsfr
//MD3U32 = dat1;
////dat1 用户给定
//MD5U16 = data2;
////dat2 用户给定
//ARCON = 6 << 5;
////32 位/16 位,除法模式
//OPCON = 1;
////启动计算
//while((OPCON & 1) != 0);
////等待计算完成
//res = MD3U32;
////32 位商,16 位余数在 MD5U16 中
//////////////////////////////////////////////////////////////////////////////////
////左移或右移:
//////////////////////////////////////////////////////////////////////////////////
//unsigned long res;
//unsigned long dat1;
//unsigned char num;
////移位的位数, 用户给定
//MD3U32 = dat1;
////dat1 用户给定
//ARCON = (2 << 5) + num;
////32 位左移模式
////ARCON = (1 << 5) + num;
////32 位右移模式
//OPCON = 1;
////启动计算
//while((OPCON & 1) != 0);
////等待计算完成
//res = MD3U32;
////32 位结果
      while(1);
      
}

ercircle 发表于 2025-9-3 11:38:59

水水水木木木 发表于 2025-9-3 11:36
我将int32去掉了,实测是4.5us。确实快了很多。代码如下。
half_cmd = (SWING_HW * M_q15) >> 15;
我再将 ...

注意keil选项里编译等级也会影响这个速度


水水水木木木 发表于 2025-9-3 11:41:50

ercircle 发表于 2025-9-3 10:46
官网下载最新版本:

https://www.stcaimcu.com/data/download/Library/STC8_MDU16.LIB

所以是不是要换支持MDU32的单片机?支持MDU32的单片机型号不多,最强大的应该是STC32G和AI8051U了吧?为了兼容32位和8位,显然AI8051U最好?

水水水木木木 发表于 2025-9-3 11:45:00

ercircle 发表于 2025-9-3 11:38
注意keil选项里编译等级也会影响这个速度

8051还能优化啊。这我第一次知道。这个等级一般建议多少?7级吗?我是默认的0级测试的。你用我的语句测试,用硬件库这种。
half_cmd = ((int32_t)SWING_HW * (uint16_t)M_q15) >> 15;
页: 1 [2] 3 4
查看完整版本: 关于硬件乘除法的问题。