【STM32F407的DSP教程】第22章DSP矩阵运算-放缩,乘法和
转置矩阵
完整版教程下载地址:
第22章      DSP矩阵运算-放缩,乘法和转置矩阵
本期教程主要讲解矩阵运算中的放缩,乘法和转置。
22.1 初学者重要提⽰
22.2 DSP基础运算指令
22.3 矩阵放缩(MatScale)
22.4 矩阵乘法(MatMult)
22.5 转置矩阵(MatTrans)
22.6 实验例程说明(MDK)
22.7 实验例程说明(IAR)
22.8 总结
22.1 初学者重要提⽰
1.  ARM提供的DSP库逆矩阵求法有局限性,通过Matlab验证是可以求逆矩阵的,⽽DSP库却不能正确求解。
2. 注意定点数的矩阵乘法运算中溢出问题。
22.2 DSP基础运算指令
本章⽤到的DSP指令在前⾯章节都已经讲解过。
22.3 矩阵放缩(MatScale)
以3*3矩阵为例,矩阵放缩的实现公式如下:
22.3.1 函数arm_mat_scale_f32
函数原型:
arm_status arm_mat_scale_f32(
const arm_matrix_instance_f32 * pSrc,
float32_t                scale,
arm_matrix_instance_f32 * pDst)
函数描述:
这个函数⽤于浮点格式的矩阵数据的放缩。
函数参数:
第1个参数是源矩阵地址。
第2个参数是放缩系数。
第3个参数是放缩后的⽬的数据地址。
返回值,ARM_MATH_SIZE_MISMATCH表⽰源矩阵和⽬标矩阵⾏列不⼀致,ARM_MATH_SUCCESS表⽰成功。注意事项:
矩阵在数组中的存储是从左到右,再从上到下。
22.3.2 函数arm_mat_scale_q31
函数原型:
arm_status arm_mat_scale_q31(
const arm_matrix_instance_q31 * pSrc,
q31_t                    scaleFract,
int32_t                  shift,
arm_matrix_instance_q31 * pDst)
函数描述:
这个函数⽤于定点Q31格式的矩阵数据的放缩。
函数参数:
第1个参数是源矩阵地址。
第2个参数是放缩系数。
第3个参数是移位的bit数。
第4个参数是放缩后的⽬的数据地址。
返回值,ARM_MATH_SIZE_MISMATCH表⽰源矩阵和⽬标矩阵⾏列不⼀致,ARM_MATH_SUCCESS表⽰成功。注意事项:
1. 两个1.31格式的数据相乘产⽣
2.62格式的数据,最终结果要做偏移和饱和运算产⽣1.31格式数。
2. 定点数的最终放缩⽐例计算是:scale = scaleFract * 2^shift。
3. 矩阵在数组中的存储是从左到右,再从上到下。
22.3.3 函数arm_mat_scale_q15
函数原型:
arm_status arm_mat_scale_q15(
const arm_matrix_instance_q15 * pSrc,
q15_t                    scaleFract,
int32_t                  shift,
arm_matrix_instance_q15 * pDst)
函数描述:
这个函数⽤于定点Q15格式的矩阵数据的放缩。
函数参数:
第1个参数是源矩阵地址。
第2个参数是放缩系数。
第3个参数是移位的bit数。
第4个参数是放缩后的⽬的数据地址。
返回值,ARM_MATH_SIZE_MISMATCH表⽰源矩阵和⽬标矩阵⾏列不⼀致,ARM_MATH_SUCCESS表⽰成功。注意事项:
1. 两个1.15格式的数据相乘产⽣
2.30格式的数据,最终结果要做偏移和饱和运算产⽣1.15格式数据。
2. 定点数的最终放缩⽐例计算是:scale = scaleFract * 2^shift。
3. 矩阵在数组中的存储是从左到右,再从上到下。
22.3.4 使⽤举例(含matlab实现)
程序设计:
/*
********************************************************************************************************* *    函数名: DSP_MatScale
*    功能说明: 矩阵放缩
*    形参: ⽆
*    返回值: ⽆
********************************************************************************************************* */
static void DSP_MatScale(void)
{
uint8_t i;
/****浮点数数组******************************************************************/
float32_t pDataA[9] = {1.1f, 1.1f, 2.1f, 2.1f, 3.1f, 3.1f, 4.1f, 4.1f, 5.1f};
float32_t scale = 1.1f;
float32_t pDataDst[9];
arm_matrix_instance_f32 pSrcA; //3⾏3列数据
arm_matrix_instance_f32 pDst;
/****定点数Q31数组******************************************************************/
q31_t pDataA1[9] = {1, 1, 2, 2, 3, 3, 4, 4, 5};
q31_t scaleFract = 10;
int32_t shift = 0;
q31_t pDataDst1[9];
arm_matrix_instance_q31 pSrcA1; //3⾏3列数据
arm_matrix_instance_q31 pDst1;
/****定点数Q15数组******************************************************************/
q15_t pDataA2[9] = {1, 1, 2, 2, 3, 3, 4, 4, 5};
q15_t scaleFract1 = 10;
int32_t shift1 = 0;
q15_t pDataDst2[9];
arm_matrix_instance_q15 pSrcA2; //3⾏3列数据
arm_matrix_instance_q15 pDst2;
/****浮点数***********************************************************************/
pSrcA.numCols = 3;
pSrcA.numRows = 3;
pSrcA.pData = pDataA;
pDst.numCols = 3;
pDst.numRows = 3;
pDst.pData = pDataDst;
printf("****浮点数******************************************\r\n");
arm_mat_scale_f32(&pSrcA, scale, &pDst);
for(i = 0; i < 9; i++)
{
printf("pDataDst[%d] = %f\r\n", i, pDataDst[i]);
}
/****定点数Q31***********************************************************************/
pSrcA1.numCols = 3;
pSrcA1.numRows = 3;
pSrcA1.pData = pDataA1;
pDst1.numCols = 3;
pDst1.numRows = 3;
pDst1.pData = pDataDst1;
printf("****定点数Q31******************************************\r\n");
arm_mat_scale_q31(&pSrcA1, scaleFract, shift, &pDst1);
for(i = 0; i < 9; i++)
{
printf("pDataDst1[%d] = %d\r\n", i, pDataDst1[i]);
}
/****定点数Q15***********************************************************************/
pSrcA2.numCols = 3;
pSrcA2.numRows = 3;
pSrcA2.pData = pDataA2;
pDst2.numCols = 3;
pDst2.numRows = 3;
pDst2.pData = pDataDst2;
printf("****定点数Q15******************************************\r\n");
arm_mat_scale_q15(&pSrcA2, scaleFract1, shift1, &pDst2);
for(i = 0; i < 9; i++)
{
printf("pDataDst2[%d] = %d\r\n", i, pDataDst2[i]);    }
}
实验现象(按下K1按键后串⼝打印):
下⾯通过matlab来实现矩阵的放缩:
22.4 矩阵乘法(MatMult)以3*3矩阵为例,矩阵乘法的实现公式如下:
22.4.1 函数arm_mat_mult_f32
函数原型:
arm_status arm_mat_mult_f32(
const arm_matrix_instance_f32 * pSrcA,
const arm_matrix_instance_f32 * pSrcB,
arm_matrix_instance_f32 * pDst)
函数描述:
这个函数⽤于浮点数的矩阵乘法。
函数参数:
printf输出格式matlab第1个参数是矩阵A的源地址。
第2个参数是矩阵B的源地址。
第3个参数是矩阵A乘以矩阵B计算结果存储的地址。
返回值,ARM_MATH_SUCCESS表⽰成功,ARM_MATH_SIZE_MISMATCH表⽰矩阵⼤⼩不⼀致。
注意事项:
1. 两个矩阵M x N和N x P相乘的结果是M x P(必须保证⼀个矩形的列数等于另⼀个矩阵的⾏数)。
2. 矩阵在数组中的存储是从左到右,再从上到下。
22.4.2 函数arm_mat_mult_q31
函数原型:
arm_status arm_mat_mult_q31(
const arm_matrix_instance_q31 * pSrcA,
const arm_matrix_instance_q31 * pSrcB,
arm_matrix_instance_q31 * pDst)
函数描述:
这个函数⽤于定点数Q31的矩阵乘法。
函数参数:
第1个参数是矩阵A的源地址。
第2个参数是矩阵B的源地址。
第3个参数是矩阵A乘以矩阵B计算结果存储的地址。
返回值,ARM_MATH_SUCCESS表⽰成功,ARM_MATH_SIZE_MISMATCH表⽰矩阵⼤⼩不⼀致。
注意事项:
1. 两个1.31格式的数据相乘产⽣
2.62格式的数据,函数的内部使⽤了64位的累加器,最终结果要做偏移和饱和运算产⽣1.31格式数据。
2. 两个矩阵M x N和N x P相乘的结果是M x P.(必须保证⼀个矩形的列数等于另⼀个矩阵的⾏数)。
3. 矩阵在数组中的存储是从左到右,再从上到下。
22.4.3 函数arm_mat_mult_q15
函数原型:
arm_status arm_mat_mult_q15(
const arm_matrix_instance_q15 * pSrcA,
const arm_matrix_instance_q15 * pSrcB,
arm_matrix_instance_q15 * pDst,
q15_t                  * pState)
函数描述:
这个函数⽤于定点数Q15的矩阵乘法。
函数参数:
第1个参数是矩阵A的源地址。
第2个参数是矩阵B的源地址。
第3个参数是矩阵A乘以矩阵B计算结果存储的地址。
第4个参数⽤于存储内部计算结果。
返回值,ARM_MATH_SUCCESS表⽰成功,ARM_MATH_SIZE_MISMATCH表⽰矩阵⼤⼩不⼀致。
注意事项:
1. 两个1.15格式数据相乘是
2.30格式,函数的内部使⽤了64位的累加器,34.30格式,最终结果将低15位截取掉并做饱和处理为1.15格
式。
2. 两个矩阵M x N和N x P相乘的结果是M x P.(必须保证⼀个矩形的列数等于另⼀个矩阵的⾏数)。
3. 矩阵在数组中的存储是从左到右,再从上到下。