完整版教程下载地址:http://www.armbbs.cn/forum.php?mod=viewthread&tid=94547
本期教程主要讲基本函数中的相反数,偏移,移位,减法和比例因子。
12.1 初学者重要提示
12.2 DSP基础运算指令
12.3 相反数(Vector Negate)
12.4 偏移(Vector Offset)
12.5 移位(Vector Shift)
12.6 减法(Vector Sub)
12.7 比例因子(Vector Scale)
12.8 实验例程说明(MDK)
12.9 实验例程说明(IAR)
12.10 总结
在这里简单的跟大家介绍一下DSP库中函数的通用格式,后面就不再赘述了。
本章用到基础运算指令:
这里特别注意饱和运算问题,在第11章的第2小节有详细说明。
这部分函数主要用于求相反数,公式描述如下:
pDst[n] = -pSrc[n], 0 <= n < blockSize.
特别注意,这部分函数支持目标指针和源指针指向相同的缓冲区。
函数原型:
1. void arm_negate_f32(
2. const float32_t * pSrc,
3. float32_t * pDst,
4. uint32_t blockSize)
5. {
6. uint32_t blkCnt; /* Loop counter */
7.
8. #if defined(ARM_MATH_NEON_EXPERIMENTAL)
9. float32x4_t vec1;
10. float32x4_t res;
11.
12. /* Compute 4 outputs at a time */
13. blkCnt = blockSize >> 2U;
14.
15. while (blkCnt > 0U)
16. {
17. /* C = -A */
18.
19. /* Negate and then store the results in the destination buffer. */
20. vec1 = vld1q_f32(pSrc);
21. res = vnegq_f32(vec1);
22. vst1q_f32(pDst, res);
23.
24. /* Increment pointers */
25. pSrc += 4;
26. pDst += 4;
27.
28. /* Decrement the loop counter */
29. blkCnt--;
30. }
31.
32. /* Tail */
33. blkCnt = blockSize & 0x3;
34.
35. #else
36. #if defined (ARM_MATH_LOOPUNROLL)
37.
38. /* Loop unrolling: Compute 4 outputs at a time */
39. blkCnt = blockSize >> 2U;
40.
41. while (blkCnt > 0U)
42. {
43. /* C = -A */
44.
45. /* Negate and store result in destination buffer. */
46. *pDst++ = -*pSrc++;
47.
48. *pDst++ = -*pSrc++;
49.
50. *pDst++ = -*pSrc++;
51.
52. *pDst++ = -*pSrc++;
53.
54. /* Decrement loop counter */
55. blkCnt--;
56. }
57.
58. /* Loop unrolling: Compute remaining outputs */
59. blkCnt = blockSize % 0x4U;
60.
61. #else
62.
63. /* Initialize blkCnt with number of samples */
64. blkCnt = blockSize;
65.
66. #endif /* #if defined (ARM_MATH_LOOPUNROLL) */
67. #endif /* #if defined(ARM_MATH_NEON_EXPERIMENTAL) */
68.
69. while (blkCnt > 0U)
70. {
71. /* C = -A */
72.
73. /* Negate and store result in destination buffer. */
74. *pDst++ = -*pSrc++;
75.
76. /* Decrement loop counter */
77. blkCnt--;
78. }
79.
80. }
函数描述:
这个函数用于求32位浮点数的相反数。
函数解析:
函数参数:
函数原型:
1. void arm_negate_q31(
2. const q31_t * pSrc,
3. q31_t * pDst,
4. uint32_t blockSize)
5. {
6. uint32_t blkCnt; /* Loop counter */
7. q31_t in; /* Temporary input variable */
8.
9. #if defined (ARM_MATH_LOOPUNROLL)
10.
11. /* Loop unrolling: Compute 4 outputs at a time */
12. blkCnt = blockSize >> 2U;
13.
14. while (blkCnt > 0U)
15. {
16. /* C = -A */
17.
18. /* Negate and store result in destination buffer. */
19. in = *pSrc++;
20. #if defined (ARM_MATH_DSP)
21. *pDst++ = __QSUB(0, in);
22. #else
23. *pDst++ = (in == INT32_MIN) ? INT32_MAX : -in;
24. #endif
25.
26. in = *pSrc++;
27. #if defined (ARM_MATH_DSP)
28. *pDst++ = __QSUB(0, in);
29. #else
30. *pDst++ = (in == INT32_MIN) ? INT32_MAX : -in;
31. #endif
32.
33. in = *pSrc++;
34. #if defined (ARM_MATH_DSP)
35. *pDst++ = __QSUB(0, in);
36. #else
37. *pDst++ = (in == INT32_MIN) ? INT32_MAX : -in;
38. #endif
39.
40. in = *pSrc++;
41. #if defined (ARM_MATH_DSP)
42. *pDst++ = __QSUB(0, in);
43. #else
44. *pDst++ = (in == INT32_MIN) ? INT32_MAX : -in;
45. #endif
46.
47. /* Decrement loop counter */
48. blkCnt--;
49. }
50.
51. /* Loop unrolling: Compute remaining outputs */
52. blkCnt = blockSize % 0x4U;
53.
54. #else
55.
56. /* Initialize blkCnt with number of samples */
57. blkCnt = blockSize;
58.
59. #endif /* #if defined (ARM_MATH_LOOPUNROLL) */
60.
61. while (blkCnt > 0U)
62. {
63. /* C = -A */
64.
65. /* Negate and store result in destination buffer. */
66. in = *pSrc++;
67. #if defined (ARM_MATH_DSP)
68. *pDst++ = __QSUB(0, in);
69. #else
70. *pDst++ = (in == INT32_MIN) ? INT32_MAX : -in;
71. #endif
72.
73. /* Decrement loop counter */
74. blkCnt--;
75. }
76.
77. }
函数描述:
用于求32位定点数的相反数。
函数解析:
函数参数:
函数原型:
1. void arm_negate_q15(
2. const q15_t * pSrc,
3. q15_t * pDst,
4. uint32_t blockSize)
5. {
6. uint32_t blkCnt; /* Loop counter */
7. q15_t in; /* Temporary input variable */
8.
9. #if defined (ARM_MATH_LOOPUNROLL)
10.
11. #if defined (ARM_MATH_DSP)
12. q31_t in1; /* Temporary input variables */
13. #endif
14.
15. /* Loop unrolling: Compute 4 outputs at a time */
16. blkCnt = blockSize >> 2U;
17.
18. while (blkCnt > 0U)
19. {
20. /* C = -A */
21.
22. #if defined (ARM_MATH_DSP)
23. /* Negate and store result in destination buffer (2 samples at a time). */
24. in1 = read_q15x2_ia ((q15_t **) &pSrc);
25. write_q15x2_ia (&pDst, __QSUB16(0, in1));
26.
27. in1 = read_q15x2_ia ((q15_t **) &pSrc);
28. write_q15x2_ia (&pDst, __QSUB16(0, in1));
29. #else
30. in = *pSrc++;
31. *pDst++ = (in == (q15_t) 0x8000) ? (q15_t) 0x7fff : -in;
32.
33. in = *pSrc++;
34. *pDst++ = (in == (q15_t) 0x8000) ? (q15_t) 0x7fff : -in;
35.
36. in = *pSrc++;
37. *pDst++ = (in == (q15_t) 0x8000) ? (q15_t) 0x7fff : -in;
38.
39. in = *pSrc++;
40. *pDst++ = (in == (q15_t) 0x8000) ? (q15_t) 0x7fff : -in;
41. #endif
42.
43. /* Decrement loop counter */
44. blkCnt--;
45. }
46.
47. /* Loop unrolling: Compute remaining outputs */
48. blkCnt = blockSize % 0x4U;
49.
50. #else
51.
52. /* Initialize blkCnt with number of samples */
53. blkCnt = blockSize;
54.
55. #endif /* #if defined (ARM_MATH_LOOPUNROLL) */
56.
57. while (blkCnt > 0U)
58. {
59. /* C = -A */
60.
61. /* Negate and store result in destination buffer. */
62. in = *pSrc++;
63. *pDst++ = (in == (q15_t) 0x8000) ? (q15_t) 0x7fff : -in;
64.
65. /* Decrement loop counter */
66. blkCnt--;
67. }
68.
69. }
函数描述:
用于求16位定点数的绝对值。
函数解析:
函数参数:
函数原型:
1. void arm_negate_q7(
2. const q7_t * pSrc,
3. q7_t * pDst,
4. uint32_t blockSize)
5. {
6. uint32_t blkCnt; /* Loop counter */
7. q7_t in; /* Temporary input variable */
8.
9. #if defined (ARM_MATH_LOOPUNROLL)
10.
11. #if defined (ARM_MATH_DSP)
12. q31_t in1; /* Temporary input variable */
13. #endif
14.
15. /* Loop unrolling: Compute 4 outputs at a time */
16. blkCnt = blockSize >> 2U;
17.
18. while (blkCnt > 0U)
19. {
20. /* C = -A */
21.
22. #if defined (ARM_MATH_DSP)
23. /* Negate and store result in destination buffer (4 samples at a time). */
24. in1 = read_q7x4_ia ((q7_t **) &pSrc);
25. write_q7x4_ia (&pDst, __QSUB8(0, in1));
26. #else
27. in = *pSrc++;
28. *pDst++ = (in == (q7_t) 0x80) ? (q7_t) 0x7f : -in;
29.
30. in = *pSrc++;
31. *pDst++ = (in == (q7_t) 0x80) ? (q7_t) 0x7f : -in;
32.
33. in = *pSrc++;
34. *pDst++ = (in == (q7_t) 0x80) ? (q7_t) 0x7f : -in;
35.
36. in = *pSrc++;
37. *pDst++ = (in == (q7_t) 0x80) ? (q7_t) 0x7f : -in;
38. #endif
39.
40. /* Decrement loop counter */
41. blkCnt--;
42. }
43.
44. /* Loop unrolling: Compute remaining outputs */
45. blkCnt = blockSize % 0x4U;
46.
47. #else
48.
49. /* Initialize blkCnt with number of samples */
50. blkCnt = blockSize;
51.
52. #endif /* #if defined (ARM_MATH_LOOPUNROLL) */
53.
54. while (blkCnt > 0U)
55. {
56. /* C = -A */
57.
58. /* Negate and store result in destination buffer. */
59. in = *pSrc++;
60.
61. #if defined (ARM_MATH_DSP)
62. *pDst++ = (q7_t) __QSUB(0, in);
63. #else
64. *pDst++ = (in == (q7_t) 0x80) ? (q7_t) 0x7f : -in;
65. #endif
66.
67. /* Decrement loop counter */
68. blkCnt--;
69. }
70.
71. }
函数描述:
用于求8位定点数的相反数。
函数解析:
函数参数:
程序设计:
/*
*********************************************************************************************************
* 函 数 名: DSP_Negate
* 功能说明: 求相反数
* 形 参: 无
* 返 回 值: 无
*********************************************************************************************************
*/
static void DSP_Negate(void)
{
float32_t pSrc = 0.0f;
float32_t pDst;
q31_t pSrc1 = 0;
q31_t pDst1;
q15_t pSrc2 = 0;
q15_t pDst2;
q7_t pSrc3 = 0;
q7_t pDst3;
/*求相反数*********************************/
pSrc -= 1.23f;
arm_negate_f32(&pSrc, &pDst, 1);
printf("arm_negate_f32 = %f\r\n", pDst);
pSrc1 -= 1;
arm_negate_q31(&pSrc1, &pDst1, 1);
printf("arm_negate_q31 = %d\r\n", pDst1);
pSrc2 -= 1;
arm_negate_q15(&pSrc2, &pDst2, 1);
printf("arm_negate_q15 = %d\r\n", pDst2);
pSrc3 += 1;
arm_negate_q7(&pSrc3, &pDst3, 1);
printf("arm_negate_q7 = %d\r\n", pDst3);
printf("***********************************\r\n");
}
实验现象:
这部分函数主要用于求偏移,公式描述如下:
pDst[n] = pSrc[n] + offset, 0 <= n < blockSize.
注意,这部分函数支持目标指针和源指针指向相同的缓冲区。
函数原型:
1. void arm_offset_f32(
2. const float32_t * pSrc,
3. float32_t offset,
4. float32_t * pDst,
5. uint32_t blockSize)
6. {
7. uint32_t blkCnt; /* Loop counter */
8.
9. #if defined(ARM_MATH_NEON_EXPERIMENTAL)
10. float32x4_t vec1;
11. float32x4_t res;
12.
13. /* Compute 4 outputs at a time */
14. blkCnt = blockSize >> 2U;
15.
16. while (blkCnt > 0U)
17. {
18. /* C = A + offset */
19.
20. /* Add offset and then store the results in the destination buffer. */
21. vec1 = vld1q_f32(pSrc);
22. res = vaddq_f32(vec1,vdupq_n_f32(offset));
23. vst1q_f32(pDst, res);
24.
25. /* Increment pointers */
26. pSrc += 4;
27. pDst += 4;
28.
29. /* Decrement the loop counter */
30. blkCnt--;
31. }
32.
33. /* Tail */
34. blkCnt = blockSize & 0x3;
35.
36. #else
37. #if defined (ARM_MATH_LOOPUNROLL)
38.
39. /* Loop unrolling: Compute 4 outputs at a time */
40. blkCnt = blockSize >> 2U;
41.
42. while (blkCnt > 0U)
43. {
44. /* C = A + offset */
45.
46. /* Add offset and store result in destination buffer. */
47. *pDst++ = (*pSrc++) + offset;
48.
49. *pDst++ = (*pSrc++) + offset;
50.
51. *pDst++ = (*pSrc++) + offset;
52.
53. *pDst++ = (*pSrc++) + offset;
54.
55. /* Decrement loop counter */
56. blkCnt--;
57. }
58.
59. /* Loop unrolling: Compute remaining outputs */
60. blkCnt = blockSize % 0x4U;
61.
62. #else
63.
64. /* Initialize blkCnt with number of samples */
65. blkCnt = blockSize;
66.
67. #endif /* #if defined (ARM_MATH_LOOPUNROLL) */
68. #endif /* #if defined(ARM_MATH_NEON_EXPERIMENTAL) */
69.
70. while (blkCnt > 0U)
71. {
72. /* C = A + offset */
73.
74. /* Add offset and store result in destination buffer. */
75. *pDst++ = (*pSrc++) + offset;
76.
77. /* Decrement loop counter */
78. blkCnt--;
79. }
80.
81. }
函数描述:
这个函数用于求32位浮点数的偏移。
函数解析:
函数参数:
函数原型:
1. void arm_offset_q31(
2. const q31_t * pSrc,
3. q31_t offset,
4. q31_t * pDst,
5. uint32_t blockSize)
6. {
7. uint32_t blkCnt; /* Loop counter */
8.
9. #if defined (ARM_MATH_LOOPUNROLL)
10.
11. /* Loop unrolling: Compute 4 outputs at a time */
12. blkCnt = blockSize >> 2U;
13.
14. while (blkCnt > 0U)
15. {
16. /* C = A + offset */
17.
18. /* Add offset and store result in destination buffer. */
19. #if defined (ARM_MATH_DSP)
20. *pDst++ = __QADD(*pSrc++, offset);
21. #else
22. *pDst++ = (q31_t) clip_q63_to_q31((q63_t) * pSrc++ + offset);
23. #endif
24.
25. #if defined (ARM_MATH_DSP)
26. *pDst++ = __QADD(*pSrc++, offset);
27. #else
28. *pDst++ = (q31_t) clip_q63_to_q31((q63_t) * pSrc++ + offset);
29. #endif
30.
31. #if defined (ARM_MATH_DSP)
32. *pDst++ = __QADD(*pSrc++, offset);
33. #else
34. *pDst++ = (q31_t) clip_q63_to_q31((q63_t) * pSrc++ + offset);
35. #endif
36.
37. #if defined (ARM_MATH_DSP)
38. *pDst++ = __QADD(*pSrc++, offset);
39. #else
40. *pDst++ = (q31_t) clip_q63_to_q31((q63_t) * pSrc++ + offset);
41. #endif
42.
43. /* Decrement loop counter */
44. blkCnt--;
45. }
46.
47. /* Loop unrolling: Compute remaining outputs */
48. blkCnt = blockSize % 0x4U;
49.
50. #else
51.
52. /* Initialize blkCnt with number of samples */
53. blkCnt = blockSize;
54.
55. #endif /* #if defined (ARM_MATH_LOOPUNROLL) */
56.
57. while (blkCnt > 0U)
58. {
59. /* C = A + offset */
60.
61. /* Add offset and store result in destination buffer. */
62. #if defined (ARM_MATH_DSP)
63. *pDst++ = __QADD(*pSrc++, offset);
64. #else
65. *pDst++ = (q31_t) clip_q63_to_q31((q63_t) * pSrc++ + offset);
66. #endif
67.
68. /* Decrement loop counter */
69. blkCnt--;
70. }
71.
72. }
函数描述:
这个函数用于求两个32位定点数的偏移。
函数解析:
函数参数:
函数原型:
1. void arm_offset_q15(
2. const q15_t * pSrc,
3. q15_t offset,
4. q15_t * pDst,
5. uint32_t blockSize)
6. {
7. uint32_t blkCnt; /* Loop counter */
8.
9. #if defined (ARM_MATH_LOOPUNROLL)
10.
11. #if defined (ARM_MATH_DSP)
12. q31_t offset_packed; /* Offset packed to 32 bit */
13.
14. /* Offset is packed to 32 bit in order to use SIMD32 for addition */
15. offset_packed = __PKHBT(offset, offset, 16);
16. #endif
17.
18. /* Loop unrolling: Compute 4 outputs at a time */
19. blkCnt = blockSize >> 2U;
20.
21. while (blkCnt > 0U)
22. {
23. /* C = A + offset */
24.
25. #if defined (ARM_MATH_DSP)
26. /* Add offset and store result in destination buffer (2 samples at a time). */
27. write_q15x2_ia (&pDst, __QADD16(read_q15x2_ia ((q15_t **) &pSrc), offset_packed));
28. write_q15x2_ia (&pDst, __QADD16(read_q15x2_ia ((q15_t **) &pSrc), offset_packed));
29. #else
30. *pDst++ = (q15_t) __SSAT(((q31_t) *pSrc++ + offset), 16);
31. *pDst++ = (q15_t) __SSAT(((q31_t) *pSrc++ + offset), 16);
32. *pDst++ = (q15_t) __SSAT(((q31_t) *pSrc++ + offset), 16);
33. *pDst++ = (q15_t) __SSAT(((q31_t) *pSrc++ + offset), 16);
34. #endif
35.
36. /* Decrement loop counter */
37. blkCnt--;
38. }
39.
40. /* Loop unrolling: Compute remaining outputs */
41. blkCnt = blockSize % 0x4U;
42.
43. #else
44.
45. /* Initialize blkCnt with number of samples */
46. blkCnt = blockSize;
47.
48. #endif /* #if defined (ARM_MATH_LOOPUNROLL) */
49.
50. while (blkCnt > 0U)
51. {
52. /* C = A + offset */
53.
54. /* Add offset and store result in destination buffer. */
55. #if defined (ARM_MATH_DSP)
56. *pDst++ = (q15_t) __QADD16(*pSrc++, offset);
57. #else
58. *pDst++ = (q15_t) __SSAT(((q31_t) *pSrc++ + offset), 16);
59. #endif
60.
61. /* Decrement loop counter */
62. blkCnt--;
63. }
64.
65. }
函数描述:
这个函数用于求16位定点数的偏移。
函数解析:
#define __PKHBT(ARG1, ARG2, ARG3) ( (((int32_t)(ARG1) << 0) & (int32_t)0x0000FFFF) | \
(((int32_t)(ARG2) << ARG3) & (int32_t)0xFFFF0000) )
__STATIC_FORCEINLINE q31_t read_q15x2_ia (
q15_t ** pQ15)
{
q31_t val;
memcpy (&val, *pQ15, 4);
*pQ15 += 2;
return (val);
}
作用是读取两次16位数据,返回一个32位数据,并将数据地址递增,方便下次读取。
函数参数:
函数原型:
1. void arm_offset_q7(
2. const q7_t * pSrc,
3. q7_t offset,
4. q7_t * pDst,
5. uint32_t blockSize)
6. {
7. uint32_t blkCnt; /* Loop counter */
8.
9. #if defined (ARM_MATH_LOOPUNROLL)
10.
11. #if defined (ARM_MATH_DSP)
12. q31_t offset_packed; /* Offset packed to 32 bit */
13.
14. /* Offset is packed to 32 bit in order to use SIMD32 for addition */
15. offset_packed = __PACKq7(offset, offset, offset, offset);
16. #endif
17.
18. /* Loop unrolling: Compute 4 outputs at a time */
19. blkCnt = blockSize >> 2U;
20.
21. while (blkCnt > 0U)
22. {
23. /* C = A + offset */
24.
25. #if defined (ARM_MATH_DSP)
26. /* Add offset and store result in destination buffer (4 samples at a time). */
27. write_q7x4_ia (&pDst, __QADD8(read_q7x4_ia ((q7_t **) &pSrc), offset_packed));
28. #else
29. *pDst++ = (q7_t) __SSAT(*pSrc++ + offset, 8);
30. *pDst++ = (q7_t) __SSAT(*pSrc++ + offset, 8);
31. *pDst++ = (q7_t) __SSAT(*pSrc++ + offset, 8);
32. *pDst++ = (q7_t) __SSAT(*pSrc++ + offset, 8);
33. #endif
34.
35. /* Decrement loop counter */
36. blkCnt--;
37. }
38.
39. /* Loop unrolling: Compute remaining outputs */
40. blkCnt = blockSize % 0x4U;
41.
42. #else
43.
44. /* Initialize blkCnt with number of samples */
45. blkCnt = blockSize;
46.
47. #endif /* #if defined (ARM_MATH_LOOPUNROLL) */
48.
49. while (blkCnt > 0U)
50. {
51. /* C = A + offset */
52.
53. /* Add offset and store result in destination buffer. */
54. *pDst++ = (q7_t) __SSAT((q15_t) *pSrc++ + offset, 8);
55.
56. /* Decrement loop counter */
57. blkCnt--;
58. }
59.
60. }
函数描述:
这个函数用于求两个8位定点数的偏移。
函数解析:
__STATIC_FORCEINLINE void write_q7x4_ia (
q7_t ** pQ7,
q31_t value)
{
q31_t val = value;
memcpy (*pQ7, &val, 4);
*pQ7 += 4;
}
作用是写4次8位数据,并将数据地址递增,方便下次继续写。
函数参数:
程序设计:
/*
*********************************************************************************************************
* 函 数 名: DSP_Offset
* 功能说明: 偏移
* 形 参: 无
* 返 回 值: 无
*********************************************************************************************************
*/
static void DSP_Offset(void)
{
float32_t pSrcA = 0.0f;
float32_t Offset = 0.0f;
float32_t pDst;
q31_t pSrcA1 = 0;
q31_t Offset1 = 0;
q31_t pDst1;
q15_t pSrcA2 = 0;
q15_t Offset2 = 0;
q15_t pDst2;
q7_t pSrcA3 = 0;
q7_t Offset3 = 0;
q7_t pDst3;
/*求偏移*********************************/
Offset--;
arm_offset_f32(&pSrcA, Offset, &pDst, 1);
printf("arm_offset_f32 = %f\r\n", pDst);
Offset1--;
arm_offset_q31(&pSrcA1, Offset1, &pDst1, 1);
printf("arm_offset_q31 = %d\r\n", pDst1);
Offset2--;
arm_offset_q15(&pSrcA2, Offset2, &pDst2, 1);
printf("arm_offset_q15 = %d\r\n", pDst2);
Offset3--;
arm_offset_q7(&pSrcA3, Offset3, &pDst3, 1);
printf("arm_offset_q7 = %d\r\n", pDst3);
printf("***********************************\r\n");
}
实验现象:
这部分函数主要用于实现移位,公式描述如下:
pDst[n] = pSrc[n] << shift, 0 <= n < blockSize.
注意,这部分函数支持目标指针和源指针指向相同的缓冲区
函数原型:
1. void arm_shift_q31(
2. const q31_t * pSrc,
3. int8_t shiftBits,
4. q31_t * pDst,
5. uint32_t blockSize)
6. {
7. uint32_t blkCnt; /* Loop counter */
8. uint8_t sign = (shiftBits & 0x80); /* Sign of shiftBits */
9.
10. #if defined (ARM_MATH_LOOPUNROLL)
11.
12. q31_t in, out; /* Temporary variables */
13.
14. /* Loop unrolling: Compute 4 outputs at a time */
15. blkCnt = blockSize >> 2U;
16.
17. /* If the shift value is positive then do right shift else left shift */
18. if (sign == 0U)
19. {
20. while (blkCnt > 0U)
21. {
22. /* C = A << shiftBits */
23.
24. /* Shift input and store result in destination buffer. */
25. in = *pSrc++;
26. out = in << shiftBits;
27. if (in != (out >> shiftBits))
28. out = 0x7FFFFFFF ^ (in >> 31);
29. *pDst++ = out;
30.
31. in = *pSrc++;
32. out = in << shiftBits;
33. if (in != (out >> shiftBits))
34. out = 0x7FFFFFFF ^ (in >> 31);
35. *pDst++ = out;
36.
37. in = *pSrc++;
38. out = in << shiftBits;
39. if (in != (out >> shiftBits))
40. out = 0x7FFFFFFF ^ (in >> 31);
41. *pDst++ = out;
42.
43. in = *pSrc++;
44. out = in << shiftBits;
45. if (in != (out >> shiftBits))
46. out = 0x7FFFFFFF ^ (in >> 31);
47. *pDst++ = out;
48.
49. /* Decrement loop counter */
50. blkCnt--;
51. }
52. }
53. else
54. {
55. while (blkCnt > 0U)
56. {
57. /* C = A >> shiftBits */
58.
59. /* Shift input and store results in destination buffer. */
60. *pDst++ = (*pSrc++ >> -shiftBits);
61. *pDst++ = (*pSrc++ >> -shiftBits);
62. *pDst++ = (*pSrc++ >> -shiftBits);
63. *pDst++ = (*pSrc++ >> -shiftBits);
64.
65. /* Decrement loop counter */
66. blkCnt--;
67. }
68. }
69.
70. /* Loop unrolling: Compute remaining outputs */
71. blkCnt = blockSize % 0x4U;
72.
73. #else
74.
75. /* Initialize blkCnt with number of samples */
76. blkCnt = blockSize;
77.
78. #endif /* #if defined (ARM_MATH_LOOPUNROLL) */
79.
80. /* If the shift value is positive then do right shift else left shift */
81. if (sign == 0U)
82. {
83. while (blkCnt > 0U)
84. {
85. /* C = A << shiftBits */
86.
87. /* Shift input and store result in destination buffer. */
88. *pDst++ = clip_q63_to_q31((q63_t) *pSrc++ << shiftBits);
89.
90. /* Decrement loop counter */
91. blkCnt--;
92. }
93. }
94. else
95. {
96. while (blkCnt > 0U)
97. {
98. /* C = A >> shiftBits */
99.
100. /* Shift input and store result in destination buffer. */
101. *pDst++ = (*pSrc++ >> -shiftBits);
102.
103. /* Decrement loop counter */
104. blkCnt--;
105. }
106. }
107.
108. }
函数描述:
这个函数用于求32位定点数的左移或者右移。
函数解析:
out = 0x7FFFFFFF ^ (in >> 31) (in是正数)
= 0x7FFFFFFF ^ 0x00000000
= 0x7FFFFFFF
out = 0x7FFFFFFF ^ (in >> 31) (in是负数)
= 0x7FFFFFFF ^ 0xFFFFFFFF
= 0x80000000
__STATIC_FORCEINLINE q31_t clip_q63_to_q31(
q63_t x)
{
return ((q31_t) (x >> 32) != ((q31_t) x >> 31)) ?
((0x7FFFFFFF ^ ((q31_t) (x >> 63)))) : (q31_t) x;
}
函数参数:
函数原型:
1. void arm_shift_q15(
2. const q15_t * pSrc,
3. int8_t shiftBits,
4. q15_t * pDst,
5. uint32_t blockSize)
6. {
7. uint32_t blkCnt; /* Loop counter */
8. uint8_t sign = (shiftBits & 0x80); /* Sign of shiftBits */
9.
10. #if defined (ARM_MATH_LOOPUNROLL)
11.
12. #if defined (ARM_MATH_DSP)
13. q15_t in1, in2; /* Temporary input variables */
14. #endif
15.
16. /* Loop unrolling: Compute 4 outputs at a time */
17. blkCnt = blockSize >> 2U;
18.
19. /* If the shift value is positive then do right shift else left shift */
20. if (sign == 0U)
21. {
22. while (blkCnt > 0U)
23. {
24. /* C = A << shiftBits */
25.
26. #if defined (ARM_MATH_DSP)
27. /* read 2 samples from source */
28. in1 = *pSrc++;
29. in2 = *pSrc++;
30.
31. /* Shift the inputs and then store the results in the destination buffer. */
32. #ifndef ARM_MATH_BIG_ENDIAN
33. write_q15x2_ia (&pDst, __PKHBT(__SSAT((in1 << shiftBits), 16),
34. __SSAT((in2 << shiftBits), 16), 16));
35. #else
36. write_q15x2_ia (&pDst, __PKHBT(__SSAT((in2 << shiftBits), 16),
37. __SSAT((in1 << shiftBits), 16), 16));
38. #endif /* #ifndef ARM_MATH_BIG_ENDIAN */
39.
40. /* read 2 samples from source */
41. in1 = *pSrc++;
42. in2 = *pSrc++;
43.
44. #ifndef ARM_MATH_BIG_ENDIAN
45. write_q15x2_ia (&pDst, __PKHBT(__SSAT((in1 << shiftBits), 16),
46. __SSAT((in2 << shiftBits), 16), 16));
47. #else
48. write_q15x2_ia (&pDst, __PKHBT(__SSAT((in2 << shiftBits), 16),
49. __SSAT((in1 << shiftBits), 16), 16));
50. #endif /* #ifndef ARM_MATH_BIG_ENDIAN */
51.
52. #else
53. *pDst++ = __SSAT(((q31_t) *pSrc++ << shiftBits), 16);
54. *pDst++ = __SSAT(((q31_t) *pSrc++ << shiftBits), 16);
55. *pDst++ = __SSAT(((q31_t) *pSrc++ << shiftBits), 16);
56. *pDst++ = __SSAT(((q31_t) *pSrc++ << shiftBits), 16);
57. #endif
58.
59. /* Decrement loop counter */
60. blkCnt--;
61. }
62. }
63. else
64. {
65. while (blkCnt > 0U)
66. {
67. /* C = A >> shiftBits */
68.
69. #if defined (ARM_MATH_DSP)
70. /* read 2 samples from source */
71. in1 = *pSrc++;
72. in2 = *pSrc++;
73.
74. /* Shift the inputs and then store the results in the destination buffer. */
75. #ifndef ARM_MATH_BIG_ENDIAN
76. write_q15x2_ia (&pDst, __PKHBT((in1 >> -shiftBits),
77. (in2 >> -shiftBits), 16));
78. #else
79. write_q15x2_ia (&pDst, __PKHBT((in2 >> -shiftBits),
80. (in1 >> -shiftBits), 16));
81. #endif /* #ifndef ARM_MATH_BIG_ENDIAN */
82.
83. /* read 2 samples from source */
84. in1 = *pSrc++;
85. in2 = *pSrc++;
86.
87. #ifndef ARM_MATH_BIG_ENDIAN
88. write_q15x2_ia (&pDst, __PKHBT((in1 >> -shiftBits),
89. (in2 >> -shiftBits), 16));
90. #else
91. write_q15x2_ia (&pDst, __PKHBT((in2 >> -shiftBits),
92. (in1 >> -shiftBits), 16));
93. #endif /* #ifndef ARM_MATH_BIG_ENDIAN */
94.
95. #else
96. *pDst++ = (*pSrc++ >> -shiftBits);
97. *pDst++ = (*pSrc++ >> -shiftBits);
98. *pDst++ = (*pSrc++ >> -shiftBits);
99. *pDst++ = (*pSrc++ >> -shiftBits);
100. #endif
101.
102. /* Decrement loop counter */
103. blkCnt--;
104. }
105. }
106.
107. /* Loop unrolling: Compute remaining outputs */
108. blkCnt = blockSize % 0x4U;
109.
110. #else
111.
112. /* Initialize blkCnt with number of samples */
113. blkCnt = blockSize;
114.
115. #endif /* #if defined (ARM_MATH_LOOPUNROLL) */
116.
117. /* If the shift value is positive then do right shift else left shift */
118. if (sign == 0U)
119. {
120. while (blkCnt > 0U)
121. {
122. /* C = A << shiftBits */
123.
124. /* Shift input and store result in destination buffer. */
125. *pDst++ = __SSAT(((q31_t) *pSrc++ << shiftBits), 16);
126.
127. /* Decrement loop counter */
128. blkCnt--;
129. }
130. }
131. else
132. {
133. while (blkCnt > 0U)
134. {
135. /* C = A >> shiftBits */
136.
137. /* Shift input and store result in destination buffer. */
138. *pDst++ = (*pSrc++ >> -shiftBits);
139.
140. /* Decrement loop counter */
141. blkCnt--;
142. }
143. }
144.
145. }
函数描述:
这个函数用于求16位定点数的左移或者右移。
函数解析:
__STATIC_FORCEINLINE void write_q15x2_ia (
q15_t ** pQ15,
q31_t value)
{
q31_t val = value;
memcpy (*pQ15, &val, 4);
*pQ15 += 2;
}
函数__PKHBT也是SIMD指令,作用是将将两个16位的数据合并成32位数据。用C实现的话,如下:
#define __PKHBT(ARG1, ARG2, ARG3) ( (((int32_t)(ARG1) << 0) & (int32_t)0x0000FFFF) | \
(((int32_t)(ARG2) << ARG3) & (int32_t)0xFFFF0000) )
函数参数:
函数原型:
1. void arm_shift_q7(
2. const q7_t * pSrc,
3. int8_t shiftBits,
4. q7_t * pDst,
5. uint32_t blockSize)
6. {
7. uint32_t blkCnt; /* Loop counter */
8. uint8_t sign = (shiftBits & 0x80); /* Sign of shiftBits */
9.
10. #if defined (ARM_MATH_LOOPUNROLL)
11.
12. #if defined (ARM_MATH_DSP)
13. q7_t in1, in2, in3, in4; /* Temporary input variables */
14. #endif
15.
16. /* Loop unrolling: Compute 4 outputs at a time */
17. blkCnt = blockSize >> 2U;
18.
19. /* If the shift value is positive then do right shift else left shift */
20. if (sign == 0U)
21. {
22. while (blkCnt > 0U)
23. {
24. /* C = A << shiftBits */
25.
26. #if defined (ARM_MATH_DSP)
27. /* Read 4 inputs */
28. in1 = *pSrc++;
29. in2 = *pSrc++;
30. in3 = *pSrc++;
31. in4 = *pSrc++;
32.
33. /* Pack and store result in destination buffer (in single write) */
34. write_q7x4_ia (&pDst, __PACKq7(__SSAT((in1 << shiftBits), 8),
35. __SSAT((in2 << shiftBits), 8),
36. __SSAT((in3 << shiftBits), 8),
37. __SSAT((in4 << shiftBits), 8) ));
38. #else
39. *pDst++ = (q7_t) __SSAT(((q15_t) *pSrc++ << shiftBits), 8);
40. *pDst++ = (q7_t) __SSAT(((q15_t) *pSrc++ << shiftBits), 8);
41. *pDst++ = (q7_t) __SSAT(((q15_t) *pSrc++ << shiftBits), 8);
42. *pDst++ = (q7_t) __SSAT(((q15_t) *pSrc++ << shiftBits), 8);
43. #endif
44.
45. /* Decrement loop counter */
46. blkCnt--;
47. }
48. }
49. else
50. {
51. while (blkCnt > 0U)
52. {
53. /* C = A >> shiftBits */
54.
55. #if defined (ARM_MATH_DSP)
56. /* Read 4 inputs */
57. in1 = *pSrc++;
58. in2 = *pSrc++;
59. in3 = *pSrc++;
60. in4 = *pSrc++;
61.
62. /* Pack and store result in destination buffer (in single write) */
63. write_q7x4_ia (&pDst, __PACKq7((in1 >> -shiftBits),
64. (in2 >> -shiftBits),
65. (in3 >> -shiftBits),
66. (in4 >> -shiftBits) ));
67. #else
68. *pDst++ = (*pSrc++ >> -shiftBits);
69. *pDst++ = (*pSrc++ >> -shiftBits);
70. *pDst++ = (*pSrc++ >> -shiftBits);
71. *pDst++ = (*pSrc++ >> -shiftBits);
72. #endif
73.
74. /* Decrement loop counter */
75. blkCnt--;
76. }
77. }
78.
79. /* Loop unrolling: Compute remaining outputs */
80. blkCnt = blockSize % 0x4U;
81.
82. #else
83.
84. /* Initialize blkCnt with number of samples */
85. blkCnt = blockSize;
86.
87. #endif /* #if defined (ARM_MATH_LOOPUNROLL) */
88.
89. /* If the shift value is positive then do right shift else left shift */
90. if (sign == 0U)
91. {
92. while (blkCnt > 0U)
93. {
94. /* C = A << shiftBits */
95.
96. /* Shift input and store result in destination buffer. */
97. *pDst++ = (q7_t) __SSAT(((q15_t) *pSrc++ << shiftBits), 8);
98.
99. /* Decrement loop counter */
100. blkCnt--;
101. }
102. }
103. else
104. {
105. while (blkCnt > 0U)
106. {
107. /* C = A >> shiftBits */
108.
109. /* Shift input and store result in destination buffer. */
110. *pDst++ = (*pSrc++ >> -shiftBits);
111.
112. /* Decrement loop counter */
113. blkCnt--;
114. }
115. }
116.
117. }
函数描述:
这个函数用于求8位定点数的左移或者右移。
函数解析:
__STATIC_FORCEINLINE void write_q7x4_ia (
q7_t ** pQ7,
q31_t value)
{
q31_t val = value;
memcpy (*pQ7, &val, 4);
*pQ7 += 4;
}
函数__PACKq7作用是将将4个8位的数据合并成32位数据,实现代码如下:
#define __PACKq7(v0,v1,v2,v3) ( (((int32_t)(v0) << 0) & (int32_t)0x000000FF) | \
(((int32_t)(v1) << 8) & (int32_t)0x0000FF00) | \
(((int32_t)(v2) << 16) & (int32_t)0x00FF0000) | \
(((int32_t)(v3) << 24) & (int32_t)0xFF000000) )
函数参数:
程序设计:
/*
*********************************************************************************************************
* 函 数 名: DSP_Shift
* 功能说明: 移位
* 形 参: 无
* 返 回 值: 无
*********************************************************************************************************
*/
static void DSP_Shift(void)
{
q31_t pSrcA1 = 0x88886666;
q31_t pDst1;
q15_t pSrcA2 = 0x8866;
q15_t pDst2;
q7_t pSrcA3 = 0x86;
q7_t pDst3;
/*求移位*********************************/
arm_shift_q31(&pSrcA1, 3, &pDst1, 1);
printf("arm_shift_q31 = %8x\r\n", pDst1);
arm_shift_q15(&pSrcA2, -3, &pDst2, 1);
printf("arm_shift_q15 = %4x\r\n", pDst2);
arm_shift_q7(&pSrcA3, 3, &pDst3, 1);
printf("arm_shift_q7 = %2x\r\n", pDst3);
printf("***********************************\r\n");
}
实验现象:
这里特别注意Q31和Q7的计算结果,表示负数已经饱和到了最小值。另外注意,对于负数来说,右移时,右侧补1,左移时,左侧补0。
这部分函数主要用于实现减法,公式描述如下:
pDst[n] = pSrcA[n] - pSrcB[n], 0 <= n < blockSize。
函数原型:
1. void arm_sub_f32(
2. const float32_t * pSrcA,
3. const float32_t * pSrcB,
4. float32_t * pDst,
5. uint32_t blockSize)
6. {
7. uint32_t blkCnt; /* Loop counter */
8.
9. #if defined(ARM_MATH_NEON)
10. float32x4_t vec1;
11. float32x4_t vec2;
12. float32x4_t res;
13.
14. /* Compute 4 outputs at a time */
15. blkCnt = blockSize >> 2U;
16.
17. while (blkCnt > 0U)
18. {
19. /* C = A - B */
20.
21. /* Subtract and then store the results in the destination buffer. */
22. vec1 = vld1q_f32(pSrcA);
23. vec2 = vld1q_f32(pSrcB);
24. res = vsubq_f32(vec1, vec2);
25. vst1q_f32(pDst, res);
26.
27. /* Increment pointers */
28. pSrcA += 4;
29. pSrcB += 4;
30. pDst += 4;
31.
32. /* Decrement the loop counter */
33. blkCnt--;
34. }
35.
36. /* Tail */
37. blkCnt = blockSize & 0x3;
38.
39. #else
40. #if defined (ARM_MATH_LOOPUNROLL)
41.
42. /* Loop unrolling: Compute 4 outputs at a time */
43. blkCnt = blockSize >> 2U;
44.
45. while (blkCnt > 0U)
46. {
47. /* C = A - B */
48.
49. /* Subtract and store result in destination buffer. */
50. *pDst++ = (*pSrcA++) - (*pSrcB++);
51.
52. *pDst++ = (*pSrcA++) - (*pSrcB++);
53.
54. *pDst++ = (*pSrcA++) - (*pSrcB++);
55.
56. *pDst++ = (*pSrcA++) - (*pSrcB++);
57.
58. /* Decrement loop counter */
59. blkCnt--;
60. }
61.
62. /* Loop unrolling: Compute remaining outputs */
63. blkCnt = blockSize % 0x4U;
64.
65. #else
66.
67. /* Initialize blkCnt with number of samples */
68. blkCnt = blockSize;
69.
70. #endif /* #if defined (ARM_MATH_LOOPUNROLL) */
71. #endif /* #if defined(ARM_MATH_NEON) */
72.
73. while (blkCnt > 0U)
74. {
75. /* C = A - B */
76.
77. /* Subtract and store result in destination buffer. */
78. *pDst++ = (*pSrcA++) - (*pSrcB++);
79.
80. /* Decrement loop counter */
81. blkCnt--;
82. }
83.
84. }
函数描述:
这个函数用于求32位浮点数的减法。
函数解析:
函数参数:
函数原型:
1. void arm_sub_q31(
2. const q31_t * pSrcA,
3. const q31_t * pSrcB,
4. q31_t * pDst,
5. uint32_t blockSize)
6. {
7. uint32_t blkCnt; /* Loop counter */
8.
9. #if defined (ARM_MATH_LOOPUNROLL)
10.
11. /* Loop unrolling: Compute 4 outputs at a time */
12. blkCnt = blockSize >> 2U;
13.
14. while (blkCnt > 0U)
15. {
16. /* C = A - B */
17.
18. /* Subtract and store result in destination buffer. */
19. *pDst++ = __QSUB(*pSrcA++, *pSrcB++);
20.
21. *pDst++ = __QSUB(*pSrcA++, *pSrcB++);
22.
23. *pDst++ = __QSUB(*pSrcA++, *pSrcB++);
24.
25. *pDst++ = __QSUB(*pSrcA++, *pSrcB++);
26.
27. /* Decrement loop counter */
28. blkCnt--;
29. }
30.
31. /* Loop unrolling: Compute remaining outputs */
32. blkCnt = blockSize % 0x4U;
33.
34. #else
35.
36. /* Initialize blkCnt with number of samples */
37. blkCnt = blockSize;
38.
39. #endif /* #if defined (ARM_MATH_LOOPUNROLL) */
40.
41. while (blkCnt > 0U)
42. {
43. /* C = A - B */
44.
45. /* Subtract and store result in destination buffer. */
46. *pDst++ = __QSUB(*pSrcA++, *pSrcB++);
47.
48. /* Decrement loop counter */
49. blkCnt--;
50. }
51.
52. }
函数描述:
这个函数用于求32位定点数的减法。
函数解析:
函数参数:
函数原型:
1. void arm_sub_q15(
2. const q15_t * pSrcA,
3. const q15_t * pSrcB,
4. q15_t * pDst,
5. uint32_t blockSize)
6. {
7. uint32_t blkCnt; /* Loop counter */
8.
9. #if defined (ARM_MATH_LOOPUNROLL)
10.
11. #if defined (ARM_MATH_DSP)
12. q31_t inA1, inA2;
13. q31_t inB1, inB2;
14. #endif
15.
16. /* Loop unrolling: Compute 4 outputs at a time */
17. blkCnt = blockSize >> 2U;
18.
19. while (blkCnt > 0U)
20. {
21. /* C = A - B */
22.
23. #if defined (ARM_MATH_DSP)
24. /* read 2 times 2 samples at a time from sourceA */
25. inA1 = read_q15x2_ia ((q15_t **) &pSrcA);
26. inA2 = read_q15x2_ia ((q15_t **) &pSrcA);
27. /* read 2 times 2 samples at a time from sourceB */
28. inB1 = read_q15x2_ia ((q15_t **) &pSrcB);
29. inB2 = read_q15x2_ia ((q15_t **) &pSrcB);
30.
31. /* Subtract and store 2 times 2 samples at a time */
32. write_q15x2_ia (&pDst, __QSUB16(inA1, inB1));
33. write_q15x2_ia (&pDst, __QSUB16(inA2, inB2));
34. #else
35. *pDst++ = (q15_t) __SSAT(((q31_t) *pSrcA++ - *pSrcB++), 16);
36. *pDst++ = (q15_t) __SSAT(((q31_t) *pSrcA++ - *pSrcB++), 16);
37. *pDst++ = (q15_t) __SSAT(((q31_t) *pSrcA++ - *pSrcB++), 16);
38. *pDst++ = (q15_t) __SSAT(((q31_t) *pSrcA++ - *pSrcB++), 16);
39. #endif
40.
41. /* Decrement loop counter */
42. blkCnt--;
43. }
44.
45. /* Loop unrolling: Compute remaining outputs */
46. blkCnt = blockSize % 0x4U;
47.
48. #else
49.
50. /* Initialize blkCnt with number of samples */
51. blkCnt = blockSize;
52.
53. #endif /* #if defined (ARM_MATH_LOOPUNROLL) */
54.
55. while (blkCnt > 0U)
56. {
57. /* C = A - B */
58.
59. /* Subtract and store result in destination buffer. */
60. #if defined (ARM_MATH_DSP)
61. *pDst++ = (q15_t) __QSUB16(*pSrcA++, *pSrcB++);
62. #else
63. *pDst++ = (q15_t) __SSAT(((q31_t) *pSrcA++ - *pSrcB++), 16);
64. #endif
65.
66. /* Decrement loop counter */
67. blkCnt--;
68. }
69.
70. }
函数描述:
这个函数用于求16位定点数的减法。
函数解析:
函数参数:
函数原型:
1. void arm_sub_q7(
2. const q7_t * pSrcA,
3. const q7_t * pSrcB,
4. q7_t * pDst,
5. uint32_t blockSize)
6. {
7. uint32_t blkCnt; /* Loop counter */
8.
9. #if defined (ARM_MATH_LOOPUNROLL)
10.
11. /* Loop unrolling: Compute 4 outputs at a time */
12. blkCnt = blockSize >> 2U;
13.
14. while (blkCnt > 0U)
15. {
16. /* C = A - B */
17.
18. #if defined (ARM_MATH_DSP)
19. /* Subtract and store result in destination buffer (4 samples at a time). */
20. write_q7x4_ia (&pDst, __QSUB8(read_q7x4_ia ((q7_t **) &pSrcA), read_q7x4_ia ((q7_t **) &pSrcB)));
21. #else
22. *pDst++ = (q7_t) __SSAT((q15_t) *pSrcA++ - *pSrcB++, 8);
23. *pDst++ = (q7_t) __SSAT((q15_t) *pSrcA++ - *pSrcB++, 8);
24. *pDst++ = (q7_t) __SSAT((q15_t) *pSrcA++ - *pSrcB++, 8);
25. *pDst++ = (q7_t) __SSAT((q15_t) *pSrcA++ - *pSrcB++, 8);
26. #endif
27.
28. /* Decrement loop counter */
29. blkCnt--;
30. }
31.
32. /* Loop unrolling: Compute remaining outputs */
33. blkCnt = blockSize % 0x4U;
34.
35. #else
36.
37. /* Initialize blkCnt with number of samples */
38. blkCnt = blockSize;
39.
40. #endif /* #if defined (ARM_MATH_LOOPUNROLL) */
41.
42. while (blkCnt > 0U)
43. {
44. /* C = A - B */
45.
46. /* Subtract and store result in destination buffer. */
47. *pDst++ = (q7_t) __SSAT((q15_t) *pSrcA++ - *pSrcB++, 8);
48.
49. /* Decrement loop counter */
50. blkCnt--;
51. }
52.
53. }
函数描述:
这个函数用于求8位定点数的乘法。
函数解析:
函数__QSUB8实现一次计算4个Q7格式减法。
函数参数:
程序设计:
/*
*********************************************************************************************************
* 函 数 名: DSP_Sub
* 功能说明: 减法
* 形 参: 无
* 返 回 值: 无
*********************************************************************************************************
*/
static void DSP_Sub(void)
{
float32_t pSrcA[5] = {1.0f,1.0f,1.0f,1.0f,1.0f};
float32_t pSrcB[5] = {1.0f,1.0f,1.0f,1.0f,1.0f};
float32_t pDst[5];
q31_t pSrcA1[5] = {1,1,1,1,1};
q31_t pSrcB1[5] = {1,1,1,1,1};
q31_t pDst1[5];
q15_t pSrcA2[5] = {1,1,1,1,1};
q15_t pSrcB2[5] = {1,1,1,1,1};
q15_t pDst2[5];
q7_t pSrcA3[5] = {0x70,1,1,1,1};
q7_t pSrcB3[5] = {0x7f,1,1,1,1};
q7_t pDst3[5];
/*求减法*********************************/
pSrcA[0] += 1.1f;
arm_sub_f32(pSrcA, pSrcB, pDst, 5);
printf("arm_sub_f32 = %f\r\n", pDst[0]);
pSrcA1[0] += 1;
arm_sub_q31(pSrcA1, pSrcB1, pDst1, 5);
printf("arm_sub_q31 = %d\r\n", pDst1[0]);
pSrcA2[0] += 1;
arm_sub_q15(pSrcA2, pSrcB2, pDst2, 5);
printf("arm_sub_q15 = %d\r\n", pDst2[0]);
pSrcA3[0] += 1;
arm_sub_q7(pSrcA3, pSrcB3, pDst3, 5);
printf("arm_sub_q7 = %d\r\n", pDst3[0]);
printf("***********************************\r\n");
}
实验现象:
这部分函数主要用于实现数据的比例放大和缩小,浮点数据公式描述如下:
pDst[n] = pSrc[n] * scale, 0 <= n < blockSize.
如果是Q31,Q15,Q7格式的数据,公式描述如下:
pDst[n] = (pSrc[n] * scaleFract) << shift, 0 <= n < blockSize.
这种情况下,比例因子就是:
scale = scaleFract * 2^shift.
注意,这部分函数支持目标指针和源指针指向相同的缓冲区
函数原型:
1. void arm_scale_f32(
2. const float32_t *pSrc,
3. float32_t scale,
4. float32_t *pDst,
5. uint32_t blockSize)
6. {
7. uint32_t blkCnt; /* Loop counter */
8. #if defined(ARM_MATH_NEON_EXPERIMENTAL)
9. float32x4_t vec1;
10. float32x4_t res;
11.
12. /* Compute 4 outputs at a time */
13. blkCnt = blockSize >> 2U;
14.
15. while (blkCnt > 0U)
16. {
17. /* C = A * scale */
18.
19. /* Scale the input and then store the results in the destination buffer. */
20. vec1 = vld1q_f32(pSrc);
21. res = vmulq_f32(vec1, vdupq_n_f32(scale));
22. vst1q_f32(pDst, res);
23.
24. /* Increment pointers */
25. pSrc += 4;
26. pDst += 4;
27.
28. /* Decrement the loop counter */
29. blkCnt--;
30. }
31.
32. /* Tail */
33. blkCnt = blockSize & 0x3;
34.
35. #else
36. #if defined (ARM_MATH_LOOPUNROLL)
37.
38. /* Loop unrolling: Compute 4 outputs at a time */
39. blkCnt = blockSize >> 2U;
40.
41. while (blkCnt > 0U)
42. {
43. /* C = A * scale */
44.
45. /* Scale input and store result in destination buffer. */
46. *pDst++ = (*pSrc++) * scale;
47.
48. *pDst++ = (*pSrc++) * scale;
49.
50. *pDst++ = (*pSrc++) * scale;
51.
52. *pDst++ = (*pSrc++) * scale;
53.
54. /* Decrement loop counter */
55. blkCnt--;
56. }
57.
58. /* Loop unrolling: Compute remaining outputs */
59. blkCnt = blockSize % 0x4U;
60.
61. #else
62.
63. /* Initialize blkCnt with number of samples */
64. blkCnt = blockSize;
65.
66. #endif /* #if defined (ARM_MATH_LOOPUNROLL) */
67. #endif /* #if defined(ARM_MATH_NEON_EXPERIMENTAL) */
68.
69. while (blkCnt > 0U)
70. {
71. /* C = A * scale */
72.
73. /* Scale input and store result in destination buffer. */
74. *pDst++ = (*pSrc++) * scale;
75.
76. /* Decrement loop counter */
77. blkCnt--;
78. }
79.
80. }
函数描述:
这个函数用于求32位浮点数的比例因子计算。
函数解析:
函数参数:
函数原型:
1. void arm_scale_q31(
2. const q31_t *pSrc,
3. q31_t scaleFract,
4. int8_t shift,
5. q31_t *pDst,
6. uint32_t blockSize)
7. {
8. uint32_t blkCnt; /* Loop counter */
9. q31_t in, out; /* Temporary variables */
10. int8_t kShift = shift + 1; /* Shift to apply after scaling */
11. int8_t sign = (kShift & 0x80);
12.
13. #if defined (ARM_MATH_LOOPUNROLL)
14.
15. /* Loop unrolling: Compute 4 outputs at a time */
16. blkCnt = blockSize >> 2U;
17.
18. if (sign == 0U)
19. {
20. while (blkCnt > 0U)
21. {
22. /* C = A * scale */
23.
24. /* Scale input and store result in destination buffer. */
25. in = *pSrc++; /* read input from source */
26. in = ((q63_t) in * scaleFract) >> 32; /* multiply input with scaler value */
27. out = in << kShift; /* apply shifting */
28. if (in != (out >> kShift)) /* saturate the result */
29. out = 0x7FFFFFFF ^ (in >> 31);
30. *pDst++ = out; /* Store result destination */
31.
32. in = *pSrc++;
33. in = ((q63_t) in * scaleFract) >> 32;
34. out = in << kShift;
35. if (in != (out >> kShift))
36. out = 0x7FFFFFFF ^ (in >> 31);
37. *pDst++ = out;
38.
39. in = *pSrc++;
40. in = ((q63_t) in * scaleFract) >> 32;
41. out = in << kShift;
42. if (in != (out >> kShift))
43. out = 0x7FFFFFFF ^ (in >> 31);
44. *pDst++ = out;
45.
46. in = *pSrc++;
47. in = ((q63_t) in * scaleFract) >> 32;
48. out = in << kShift;
49. if (in != (out >> kShift))
50. out = 0x7FFFFFFF ^ (in >> 31);
51. *pDst++ = out;
52.
53. /* Decrement loop counter */
54. blkCnt--;
55. }
56. }
57. else
58. {
59. while (blkCnt > 0U)
60. {
61. /* C = A * scale */
62.
63. /* Scale input and store result in destination buffer. */
64. in = *pSrc++; /* read four inputs from source */
65. in = ((q63_t) in * scaleFract) >> 32; /* multiply input with scaler value */
66. out = in >> -kShift; /* apply shifting */
67. *pDst++ = out; /* Store result destination */
68.
69. in = *pSrc++;
70. in = ((q63_t) in * scaleFract) >> 32;
71. out = in >> -kShift;
72. *pDst++ = out;
73.
74. in = *pSrc++;
75. in = ((q63_t) in * scaleFract) >> 32;
76. out = in >> -kShift;
77. *pDst++ = out;
78.
79. in = *pSrc++;
80. in = ((q63_t) in * scaleFract) >> 32;
81. out = in >> -kShift;
82. *pDst++ = out;
83.
84. /* Decrement loop counter */
85. blkCnt--;
86. }
87. }
88.
89. /* Loop unrolling: Compute remaining outputs */
90. blkCnt = blockSize % 0x4U;
91.
92. #else
93.
94. /* Initialize blkCnt with number of samples */
95. blkCnt = blockSize;
96.
97. #endif /* #if defined (ARM_MATH_LOOPUNROLL) */
98.
99. if (sign == 0U)
100. {
101. while (blkCnt > 0U)
102. {
103. /* C = A * scale */
104.
105. /* Scale input and store result in destination buffer. */
106. in = *pSrc++;
107. in = ((q63_t) in * scaleFract) >> 32;
108. out = in << kShift;
109. if (in != (out >> kShift))
110. out = 0x7FFFFFFF ^ (in >> 31);
111. *pDst++ = out;
112.
113. /* Decrement loop counter */
114. blkCnt--;
115. }
116. }
117. else
118. {
119. while (blkCnt > 0U)
120. {
121. /* C = A * scale */
122.
123. /* Scale input and store result in destination buffer. */
124. in = *pSrc++;
125. in = ((q63_t) in * scaleFract) >> 32;
126. out = in >> -kShift;
127. *pDst++ = out;
128.
129. /* Decrement loop counter */
130. blkCnt--;
131. }
132. }
133.
134. }
函数描述:
这个函数用于求32位定点数的比例因子计算。
函数解析:
第26行,左移32位,那么结果就是2.30格式。
第27行,kShift = shift + 1,也就是out = in <<(shift + 1)多执行了一次左移操作。
相当于2.30格式,转换为2.31格式。
数值的左移仅支持将其左移后再右移相应的位数后数值不变的情况,如果不满足这个条件,那么要对输出结果做饱和运算,这里分两种情况:
out = 0x7FFFFFFF ^ (in >> 31) (in是正数)
= 0x7FFFFFFF ^ 0x00000000
= 0x7FFFFFFF
out = 0x7FFFFFFF ^ (in >> 31) (in是负数)
= 0x7FFFFFFF ^ 0xFFFFFFFF
= 0x80000000
函数参数:
函数原型:
1. void arm_shift_q15(
2. const q15_t * pSrc,
3. int8_t shiftBits,
4. q15_t * pDst,
5. uint32_t blockSize)
6. {
7. uint32_t blkCnt; /* Loop counter */
8. uint8_t sign = (shiftBits & 0x80); /* Sign of shiftBits */
9.
10. #if defined (ARM_MATH_LOOPUNROLL)
11.
12. #if defined (ARM_MATH_DSP)
13. q15_t in1, in2; /* Temporary input variables */
14. #endif
15.
16. /* Loop unrolling: Compute 4 outputs at a time */
17. blkCnt = blockSize >> 2U;
18.
19. /* If the shift value is positive then do right shift else left shift */
20. if (sign == 0U)
21. {
22. while (blkCnt > 0U)
23. {
24. /* C = A << shiftBits */
25.
26. #if defined (ARM_MATH_DSP)
27. /* read 2 samples from source */
28. in1 = *pSrc++;
29. in2 = *pSrc++;
30.
31. /* Shift the inputs and then store the results in the destination buffer. */
32. #ifndef ARM_MATH_BIG_ENDIAN
33. write_q15x2_ia (&pDst, __PKHBT(__SSAT((in1 << shiftBits), 16),
34. __SSAT((in2 << shiftBits), 16), 16));
35. #else
36. write_q15x2_ia (&pDst, __PKHBT(__SSAT((in2 << shiftBits), 16),
37. __SSAT((in1 << shiftBits), 16), 16));
38. #endif /* #ifndef ARM_MATH_BIG_ENDIAN */
39.
40. /* read 2 samples from source */
41. in1 = *pSrc++;
42. in2 = *pSrc++;
43.
44. #ifndef ARM_MATH_BIG_ENDIAN
45. write_q15x2_ia (&pDst, __PKHBT(__SSAT((in1 << shiftBits), 16),
46. __SSAT((in2 << shiftBits), 16), 16));
47. #else
48. write_q15x2_ia (&pDst, __PKHBT(__SSAT((in2 << shiftBits), 16),
49. __SSAT((in1 << shiftBits), 16), 16));
50. #endif /* #ifndef ARM_MATH_BIG_ENDIAN */
51.
52. #else
53. *pDst++ = __SSAT(((q31_t) *pSrc++ << shiftBits), 16);
54. *pDst++ = __SSAT(((q31_t) *pSrc++ << shiftBits), 16);
55. *pDst++ = __SSAT(((q31_t) *pSrc++ << shiftBits), 16);
56. *pDst++ = __SSAT(((q31_t) *pSrc++ << shiftBits), 16);
57. #endif
58.
59. /* Decrement loop counter */
60. blkCnt--;
61. }
62. }
63. else
64. {
65. while (blkCnt > 0U)
66. {
67. /* C = A >> shiftBits */
68.
69. #if defined (ARM_MATH_DSP)
70. /* read 2 samples from source */
71. in1 = *pSrc++;
72. in2 = *pSrc++;
73.
74. /* Shift the inputs and then store the results in the destination buffer. */
75. #ifndef ARM_MATH_BIG_ENDIAN
76. write_q15x2_ia (&pDst, __PKHBT((in1 >> -shiftBits),
77. (in2 >> -shiftBits), 16));
78. #else
79. write_q15x2_ia (&pDst, __PKHBT((in2 >> -shiftBits),
80. (in1 >> -shiftBits), 16));
81. #endif /* #ifndef ARM_MATH_BIG_ENDIAN */
82.
83. /* read 2 samples from source */
84. in1 = *pSrc++;
85. in2 = *pSrc++;
86.
87. #ifndef ARM_MATH_BIG_ENDIAN
88. write_q15x2_ia (&pDst, __PKHBT((in1 >> -shiftBits),
89. (in2 >> -shiftBits), 16));
90. #else
91. write_q15x2_ia (&pDst, __PKHBT((in2 >> -shiftBits),
92. (in1 >> -shiftBits), 16));
93. #endif /* #ifndef ARM_MATH_BIG_ENDIAN */
94.
95. #else
96. *pDst++ = (*pSrc++ >> -shiftBits);
97. *pDst++ = (*pSrc++ >> -shiftBits);
98. *pDst++ = (*pSrc++ >> -shiftBits);
99. *pDst++ = (*pSrc++ >> -shiftBits);
100. #endif
101.
102. /* Decrement loop counter */
103. blkCnt--;
104. }
105. }
106.
107. /* Loop unrolling: Compute remaining outputs */
108. blkCnt = blockSize % 0x4U;
109.
110. #else
111.
112. /* Initialize blkCnt with number of samples */
113. blkCnt = blockSize;
114.
115. #endif /* #if defined (ARM_MATH_LOOPUNROLL) */
116.
117. /* If the shift value is positive then do right shift else left shift */
118. if (sign == 0U)
119. {
120. while (blkCnt > 0U)
121. {
122. /* C = A << shiftBits */
123.
124. /* Shift input and store result in destination buffer. */
125. *pDst++ = __SSAT(((q31_t) *pSrc++ << shiftBits), 16);
126.
127. /* Decrement loop counter */
128. blkCnt--;
129. }
130. }
131. else
132. {
133. while (blkCnt > 0U)
134. {
135. /* C = A >> shiftBits */
136.
137. /* Shift input and store result in destination buffer. */
138. *pDst++ = (*pSrc++ >> -shiftBits);
139.
140. /* Decrement loop counter */
141. blkCnt--;
142. }
143. }
144.
145. }
函数描述:
这个函数用于求16位定点数的比例因子计算。
函数解析:
#define __PKHBT(ARG1, ARG2, ARG3) ( (((int32_t)(ARG1) << 0) & (int32_t)0x0000FFFF) | \
(((int32_t)(ARG2) << ARG3) & (int32_t)0xFFFF0000) )
函数write_q15x2_ia的原型如下:
__STATIC_FORCEINLINE void write_q15x2_ia (
q15_t ** pQ15,
q31_t value)
{
q31_t val = value;
memcpy (*pQ15, &val, 4);
*pQ15 += 2;
}
作用是写入两次Q15格式数据,组成一个Q31格式数据,并将数据地址递增,方便下次写入。
函数参数:
函数原型:
1. void arm_scale_q7(
2. const q7_t * pSrc,
3. q7_t scaleFract,
4. int8_t shift,
5. q7_t * pDst,
6. uint32_t blockSize)
7. {
8. uint32_t blkCnt; /* Loop counter */
9. int8_t kShift = 7 - shift; /* Shift to apply after scaling */
10.
11. #if defined (ARM_MATH_LOOPUNROLL)
12.
13. #if defined (ARM_MATH_DSP)
14. q7_t in1, in2, in3, in4; /* Temporary input variables */
15. q7_t out1, out2, out3, out4; /* Temporary output variables */
16. #endif
17.
18. /* Loop unrolling: Compute 4 outputs at a time */
19. blkCnt = blockSize >> 2U;
20.
21. while (blkCnt > 0U)
22. {
23. /* C = A * scale */
24.
25. #if defined (ARM_MATH_DSP)
26. /* Reading 4 inputs from memory */
27. in1 = *pSrc++;
28. in2 = *pSrc++;
29. in3 = *pSrc++;
30. in4 = *pSrc++;
31.
32. /* Scale inputs and store result in the temporary variable. */
33. out1 = (q7_t) (__SSAT(((in1) * scaleFract) >> kShift, 8));
34. out2 = (q7_t) (__SSAT(((in2) * scaleFract) >> kShift, 8));
35. out3 = (q7_t) (__SSAT(((in3) * scaleFract) >> kShift, 8));
36. out4 = (q7_t) (__SSAT(((in4) * scaleFract) >> kShift, 8));
37.
38. /* Pack and store result in destination buffer (in single write) */
39. write_q7x4_ia (&pDst, __PACKq7(out1, out2, out3, out4));
40. #else
41. *pDst++ = (q7_t) (__SSAT((((q15_t) *pSrc++ * scaleFract) >> kShift), 8));
42. *pDst++ = (q7_t) (__SSAT((((q15_t) *pSrc++ * scaleFract) >> kShift), 8));
43. *pDst++ = (q7_t) (__SSAT((((q15_t) *pSrc++ * scaleFract) >> kShift), 8));
44. *pDst++ = (q7_t) (__SSAT((((q15_t) *pSrc++ * scaleFract) >> kShift), 8));
45. #endif
46.
47. /* Decrement loop counter */
48. blkCnt--;
49. }
50.
51. /* Loop unrolling: Compute remaining outputs */
52. blkCnt = blockSize % 0x4U;
53.
54. #else
55.
56. /* Initialize blkCnt with number of samples */
57. blkCnt = blockSize;
58.
59. #endif /* #if defined (ARM_MATH_LOOPUNROLL) */
60.
61. while (blkCnt > 0U)
62. {
63. /* C = A * scale */
64.
65. /* Scale input and store result in destination buffer. */
66. *pDst++ = (q7_t) (__SSAT((((q15_t) *pSrc++ * scaleFract) >> kShift), 8));
67.
68. /* Decrement loop counter */
69. blkCnt--;
70. }
71.
72. }
函数描述:
这个函数用于求8位定点数的比例因子计算。
函数解析:
(in1 * scaleFract) >> kShift
= (in1 * scaleFract) * 2^(shift - 7)
= ((in1 * scaleFract) >>7)*(2^shift)
源数据in1格式Q7乘以比例因子scaleFract格式Q7,也就是2.14格式,再右移7bit就是2.7格式,
此时如果shift正数,那么就是当前结果左移shitf位,如果shift是负数,那么就是当前结果右移shift位。最终结果通过__SSAT做个饱和运算。
函数参数:
程序设计:
/*
*********************************************************************************************************
* 函 数 名: DSP_Scale
* 功能说明: 比例因子
* 形 参: 无
* 返 回 值: 无
*********************************************************************************************************
*/
static void DSP_Scale(void)
{
float32_t pSrcA[5] = {1.0f,1.0f,1.0f,1.0f,1.0f};
float32_t scale = 0.0f;
float32_t pDst[5];
q31_t pSrcA1[5] = {0x6fffffff,1,1,1,1};
q31_t scale1 = 0x6fffffff;
q31_t pDst1[5];
q15_t pSrcA2[5] = {0x6fff,1,1,1,1};
q15_t scale2 = 0x6fff;
q15_t pDst2[5];
q7_t pSrcA3[5] = {0x70,1,1,1,1};
q7_t scale3 = 0x6f;
q7_t pDst3[5];
/*求比例因子计算*********************************/
scale += 0.1f;
arm_scale_f32(pSrcA, scale, pDst, 5);
printf("arm_scale_f32 = %f\r\n", pDst[0]);
scale1 += 1;
arm_scale_q31(pSrcA1, scale1, 0, pDst1, 5);
printf("arm_scale_q31 = %x\r\n", pDst1[0]);
scale2 += 1;
arm_scale_q15(pSrcA2, scale2, 0, pDst2, 5);
printf("arm_scale_q15 = %x\r\n", pDst2[0]);
scale3 += 1;
arm_scale_q7(pSrcA3, scale3, 0, pDst3, 5);
printf("arm_scale_q7 = %x\r\n", pDst3[0]);
printf("***********************************\r\n");
}
实验现象:
配套例子:
V5-207_DSP基础运算(相反数,偏移,移位,减法和比例因子)
实验目的:
实验内容:
使用AC6注意事项
特别注意附件章节C的问题
上电后串口打印的信息:
波特率 115200,数据位 8,奇偶校验位无,停止位 1。
详见本章的3.5,4.5,5.4和6.5小节。
程序设计:
系统栈大小分配:
硬件外设初始化
硬件外设的初始化是在 bsp.c 文件实现:
/*
*********************************************************************************************************
* 函 数 名: bsp_Init
* 功能说明: 初始化所有的硬件设备。该函数配置CPU寄存器和外设的寄存器并初始化一些全局变量。只需要调用一次
* 形 参:无
* 返 回 值: 无
*********************************************************************************************************
*/
void bsp_Init(void)
{
/*
STM32F407 HAL 库初始化,此时系统用的还是F407自带的16MHz,HSI时钟:
- 调用函数HAL_InitTick,初始化滴答时钟中断1ms。
- 设置NVIV优先级分组为4。
*/
HAL_Init();
/*
配置系统时钟到168MHz
- 切换使用HSE。
- 此函数会更新全局变量SystemCoreClock,并重新配置HAL_InitTick。
*/
SystemClock_Config();
/*
Event Recorder:
- 可用于代码执行时间测量,MDK5.25及其以上版本才支持,IAR不支持。
- 默认不开启,如果要使能此选项,务必看V5开发板用户手册第8章
*/
#if Enable_EventRecorder == 1
/* 初始化EventRecorder并开启 */
EventRecorderInitialize(EventRecordAll, 1U);
EventRecorderStart();
#endif
bsp_InitKey(); /* 按键初始化,要放在滴答定时器之前,因为按钮检测是通过滴答定时器扫描 */
bsp_InitTimer(); /* 初始化滴答定时器 */
bsp_InitUart(); /* 初始化串口 */
bsp_InitLed(); /* 初始化LED */
bsp_InitESP8266(); /* 配置ESP8266模块相关的资源 */
}
主功能:
主程序实现如下操作:
/*
*********************************************************************************************************
* 函 数 名: main
* 功能说明: c程序入口
* 形 参:无
* 返 回 值: 错误代码(无需处理)
*********************************************************************************************************
*/
int main(void)
{
uint8_t ucKeyCode; /* 按键代码 */
bsp_Init(); /* 硬件初始化 */
PrintfLogo(); /* 打印例程信息到串口1 */
PrintfHelp(); /* 打印操作提示信息 */
bsp_StartAutoTimer(0, 100); /* 启动1个100ms的自动重装的定时器 */
/* 进入主程序循环体 */
while (1)
{
bsp_Idle(); /* 这个函数在bsp.c文件。用户可以修改这个函数实现CPU休眠和喂狗 */
/* 判断定时器超时时间 */
if (bsp_CheckTimer(0))
{
/* 每隔100ms 进来一次 */
bsp_LedToggle(2);
}
ucKeyCode = bsp_GetKey(); /* 读取键值, 无键按下时返回 KEY_NONE = 0 */
if (ucKeyCode != KEY_NONE)
{
switch (ucKeyCode)
{
case KEY_DOWN_K1: /* K1键按下,求相反数 */
DSP_Negate();
break;
case KEY_DOWN_K2: /* K2键按下, 求偏移 */
DSP_Offset();
break;
case KEY_DOWN_K3: /* K3键按下,求移位 */
DSP_Shift();
break;
case JOY_DOWN_OK: /* 摇杆OK键按下,求减法 */
DSP_Sub();
break;
case JOY_DOWN_U: /* 摇杆上键按下,求比例因子计算 */
DSP_Scale();
break;
default:
/* 其他的键值不处理 */
break;
}
}
}
}
配套例子:
V5-207_DSP基础运算(相反数,偏移,移位,减法和比例因子)
实验目的:
实验内容:
使用AC6注意事项
特别注意附件章节C的问题
上电后串口打印的信息:
波特率 115200,数据位 8,奇偶校验位无,停止位 1。
详见本章的3.5,4.5,5.4和6.5小节。
程序设计:
系统栈大小分配:
硬件外设初始化
硬件外设的初始化是在 bsp.c 文件实现:
/*
*********************************************************************************************************
* 函 数 名: bsp_Init
* 功能说明: 初始化所有的硬件设备。该函数配置CPU寄存器和外设的寄存器并初始化一些全局变量。只需要调用一次
* 形 参:无
* 返 回 值: 无
*********************************************************************************************************
*/
void bsp_Init(void)
{
/*
STM32F407 HAL 库初始化,此时系统用的还是F407自带的16MHz,HSI时钟:
- 调用函数HAL_InitTick,初始化滴答时钟中断1ms。
- 设置NVIV优先级分组为4。
*/
HAL_Init();
/*
配置系统时钟到168MHz
- 切换使用HSE。
- 此函数会更新全局变量SystemCoreClock,并重新配置HAL_InitTick。
*/
SystemClock_Config();
/*
Event Recorder:
- 可用于代码执行时间测量,MDK5.25及其以上版本才支持,IAR不支持。
- 默认不开启,如果要使能此选项,务必看V5开发板用户手册第8章
*/
#if Enable_EventRecorder == 1
/* 初始化EventRecorder并开启 */
EventRecorderInitialize(EventRecordAll, 1U);
EventRecorderStart();
#endif
bsp_InitKey(); /* 按键初始化,要放在滴答定时器之前,因为按钮检测是通过滴答定时器扫描 */
bsp_InitTimer(); /* 初始化滴答定时器 */
bsp_InitUart(); /* 初始化串口 */
bsp_InitExtIO(); /* 初始化扩展IO */
bsp_InitLed(); /* 初始化LED */
}
主功能:
主程序实现如下操作:
/*
*********************************************************************************************************
* 函 数 名: main
* 功能说明: c程序入口
* 形 参:无
* 返 回 值: 错误代码(无需处理)
*********************************************************************************************************
*/
int main(void)
{
uint8_t ucKeyCode; /* 按键代码 */
bsp_Init(); /* 硬件初始化 */
PrintfLogo(); /* 打印例程信息到串口1 */
PrintfHelp(); /* 打印操作提示信息 */
bsp_StartAutoTimer(0, 100); /* 启动1个100ms的自动重装的定时器 */
/* 进入主程序循环体 */
while (1)
{
bsp_Idle(); /* 这个函数在bsp.c文件。用户可以修改这个函数实现CPU休眠和喂狗 */
/* 判断定时器超时时间 */
if (bsp_CheckTimer(0))
{
/* 每隔100ms 进来一次 */
bsp_LedToggle(2);
}
ucKeyCode = bsp_GetKey(); /* 读取键值, 无键按下时返回 KEY_NONE = 0 */
if (ucKeyCode != KEY_NONE)
{
switch (ucKeyCode)
{
case KEY_DOWN_K1: /* K1键按下,求相反数 */
DSP_Negate();
break;
case KEY_DOWN_K2: /* K2键按下, 求偏移 */
DSP_Offset();
break;
case KEY_DOWN_K3: /* K3键按下,求移位 */
DSP_Shift();
break;
case JOY_DOWN_OK: /* 摇杆OK键按下,求减法 */
DSP_Sub();
break;
case JOY_DOWN_U: /* 摇杆上键按下,求比例因子计算 */
DSP_Scale();
break;
default:
/* 其他的键值不处理 */
break;
}
}
}
}
DSP基础函数就跟大家讲这么多,希望初学的同学多多的练习,并在自己以后的项目中多多使用,效果必将事半功倍。