如何解决fmodf是否会在stm32中引起硬故障? 编辑1:编辑2:编辑3:
我正在尝试从2个正弦波中创建一个调制波形。 为此,我需要取模(fmodf)来了解特定频率(lo_frequency)的正弦波在该时间(t)处的振幅。但是执行以下行时,我会遇到硬故障:
j = fmodf(2 * PI * lo_frequency * t,2 * PI);
您知道为什么这会给我带来麻烦吗?
编辑1:
我用my_fmodf交换了fmodf:
float my_fmodf(float x,float y){
if(y == 0){
return 0;
}
float n = x / y;
return x - n * y;
}
但是仍然会发生硬故障,当我调试它时,它甚至都不会跳入该函数(my_fmodf)。
int* create_wave(int* message){
/* Mixes the message signal at 10kHz and the carrier at 40kHz.
* When a bit of the message is 0 the amplitude is lowered to 10%.
* When a bit of the message is 1 the amplitude is 100%.
* The output of the STM32 can't be negative,thats why the wave swings between
* 0 and 256 (8bit precision for faster DAC)
*/
static int rf_frequency = 10000;
static int lo_frequency = 40000;
static int sample_rate = 100000;
int output[sample_rate];
int index,mix;
float j,t;
for(int i = 0; i <= sample_rate; i++){
t = i * 0.00000001f; // i * 10^-8
j = my_fmodf(2 * PI * lo_frequency * t,2 * PI);
if (j < 0){
j += (float) 2 * PI;
}
index = floor((16.0f / (lo_frequency/rf_frequency * 0.0001f)) * t);
if (index < 16) {
if (!message[index]) {
mix = 115 + sin1(j) * 0.1f;
} else {
mix = sin1(j);
}
} else {
break;
}
output[i] = mix;
}
return output;
}
编辑2:
我已修复警告:函数以“ chux-Reinstate Monica”建议的方式返回局部变量[-Wreturn-local-addr]的地址。
int* create_wave(int* message){
static uint16_t rf_frequency = 10000;
static uint32_t lo_frequency = 40000;
static uint32_t sample_rate = 100000;
int *output = malloc(sizeof *output * sample_rate);
uint8_t index,n,t;
for(int i = 0; i < sample_rate; i++){
t = i * 0.00000001f; // i * 10^-8
j = fmodf(2 * PI * lo_frequency * t,2 * PI);
if (j < 0){
j += 2 * PI;
}
index = floor((16.0f / (lo_frequency/rf_frequency * 0.0001f)) * t);
if (index < 16) {
if (!message[index]) {
mix = (uint8_t) floor(115 + sin1(j) * 0.1f);
} else {
mix = sin1(j);
}
} else {
break;
}
output[i] = mix;
}
return output;
}
但是现在我在这条线上遇到了硬故障:
output[i] = mix;
编辑3:
因为先前的代码包含一个非常大的缓冲区阵列,无法容纳STM32F303K8的16KB SRAM,所以我需要对其进行更改。
现在,我使用“乒乓”缓冲区,在其中将DMA的回调用于“上半传输”和“完全传输”:
void HAL_DAC_ConvHalfCpltCallbackCh1(DAC_HandleTypeDef * hdac){
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_3,GPIO_PIN_SET);
for(uint16_t i = 0; i < 128; i++){
new_value = sin_table[(i * 8) % 256];
if (message[message_index] == 0x0){
dac_buf[i] = new_value * 0.1f + 115;
} else {
dac_buf[i] = new_value;
}
}
}
void HAL_DAC_ConvCpltCallbackCh1 (DAC_HandleTypeDef * hdac){
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_RESET);
for(uint16_t i = 128; i < 256; i++){
new_value = sin_table[(i * 8) % 256];
if (message[message_index] == 0x0){
dac_buf[i] = new_value * 0.1f + 115;
} else {
dac_buf[i] = new_value;
}
}
message_index++;
if (message_index >= 16) {
message_index = 0;
// HAL_DAC_Stop_DMA (&hdac1,DAC_CHANNEL_1);
}
}
但是创建的正弦频率太低。 我限制在20kHz左右,但我需要40kHz。 我已经准备好将时钟增加8倍,以使时钟最大化: 。 我仍然可以减少计数器周期(目前为50),但是这样做的话,中断回调似乎比下一个周期要花费更长的时间。 至少这样看来,当我这样做时,输出变得非常失真。
我还尝试通过仅获取第8个正弦值来降低精度,但是 我不能再这样做了,因为这样输出就不再像正弦波了。
有什么想法可以优化回调以减少时间? 还有其他想法吗?
解决方法
fmodf()是否会在stm32中引起硬故障?
这是导致硬错误的其他代码问题。
无法编译带有足够的警告
最佳代码提示:启用所有警告。 @KamilCuk
反馈比Stackoverflow更快。
我希望在功能良好的编译器上出现类似下面的内容。
return output;
warning: function returns address of local variable [-Wreturn-local-addr]
返回本地对象
无法返回本地数组。改为分配。
// int output[sample_rate];
int *output = malloc(sizeof *output * sample_rate);
return output;
调用代码将需要free()
指针。
超出范围的阵列访问权限
static int sample_rate = 100000;
int output[sample_rate];
// for(int i = 0; i <= sample_rate; i++){
for(int i = 0; i < sample_rate; i++){
...
output[i] = mix;
}
堆栈溢出?
static int sample_rate = 100000; int output[sample_rate];
是一个很大的局部变量。也许分配或尝试一些较小的东西?
高级:精度下降
好的fmodf()
不会失去准确性。对于更精确的答案,请考虑double
数学作为中间结果。还有一种更好的方法。
float my_fmodf(float x,float y){
if(y == 0){
return 0;
}
double n = 1.0 * x / y;
return (float) (x - n * y);
}
我不能在另一个函数中使用任何功能吗?
是的。代码还有其他问题。
,每10uS 1个值仅使100kSPS相对于此宏来说不是太多。在我的设计中,我生成的> 5MSPS信号没有任何问题。通常,我在循环模式下只有一个缓冲区和DMA。首先,我填充缓冲区并开始生成。当触发一半发送DMA中断时,我用新数据填充缓冲区的前半部分。在填充后半部分时,将触发传输完成中断,然后再次重复此过程。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。