我是 Arduino 和微控制器的新手。
我在研究规格时发现,即使是同一块板子也可能具有不同的输入电压(3.3V 对 5V)的不同频率。那么问题来了,频率代表什么?它是否代表它能够运行多少行汇编代码?或者它能够输出的最大PWM频率?
另一个问题是,如果我正在为特定项目寻找板子,我如何确定我需要先验的频率,而不是尝试一切并看看哪个有效?
让我更困惑的是,当涉及到计算机 CPU 时,似乎较低频率的 CPU 实际上比较高频率的 CPU(例如 Intel)运行得更快。那么我怎么知道微控制器可以运行多快呢?
STM32F072CBU 微控制器。
我有多个 ADC 输入,希望单独读取它们。STMcubeMX 生成样板代码,假设我希望按顺序读取所有输入,但我无法弄清楚如何纠正这个问题。
这篇博文表达了我遇到的同样的问题,但给出的解决方案似乎不起作用。每次转换时打开和关闭 ADC 与返回值中的错误相关。仅当我在 STMcubeMX 中配置单个 ADC 输入,然后在不取消初始化 ADC 的情况下进行轮询时,才会返回准确的读数。
cubeMX的adc_init函数:
/* ADC init function */
static void MX_ADC_Init(void)
{
ADC_ChannelConfTypeDef sConfig;
/**Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion)
*/
hadc.Instance = ADC1;
hadc.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;
hadc.Init.Resolution = ADC_RESOLUTION_12B;
hadc.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc.Init.ScanConvMode = ADC_SCAN_DIRECTION_FORWARD;
hadc.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
hadc.Init.LowPowerAutoWait = DISABLE;
hadc.Init.LowPowerAutoPowerOff = DISABLE;
hadc.Init.ContinuousConvMode = DISABLE;
hadc.Init.DiscontinuousConvMode = DISABLE;
hadc.Init.ExternalTrigConv = ADC_SOFTWARE_START;
hadc.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; …Run Code Online (Sandbox Code Playgroud) 我正在使用 FT4222 器件以 I2c 方式对 MAX77651 进行编程。我希望能够在寄存器中写入。
我能够读取寄存器,所以我知道我没有任何硬件问题。要读取寄存器,我会这样进行:我首先发送我想要读取的寄存器,然后我只读取里面的内容。
要写入,我尝试将寄存器发送到我想要写入的位置,然后发送我想要放入寄存器中的数据。但是当我通过阅读之后进行检查时,我没有得到预期的结果。
这是我尝试编写和阅读的程序部分:
uint8 resultat=0x11;
uint8 *p_resultat=&resultat;
int chiffre = 8;
uint16 bytesToWrite2 = 1;
uint16 bytesWritten2=1;
uint8 valeur= 0x06; // Adress of register
uint8 *p_valeur=&valeur;
uint16 slaveAddr = 0x48;
// ***** reading test of 0x06 : expected value : 0xFF
FT4222_I2CMaster_Write(ftHandle,slaveAddr,p_valeur,
bytesToWrite2,&bytesWritten);
chiffre = FT4222_I2CMaster_Read(ftHandle,slaveAddr,p_resultat,1, &bytesRead);
printf("The content of the register %02X is : %02X \n " , valeur , resultat);
printf("reading success if : %d = 0 \n " , chiffre); …Run Code Online (Sandbox Code Playgroud) 我有几个用于家庭自动化的微控制器项目。我的每个节点都有一个在代码中手动设置的版本号。这个版本号是在节点启动的时候报告的,通知我运行的是哪个代码。
有时在对代码进行一些更改后会忘记更改版本号。所以必须找到一个自动解决方案。
我对解决方案有一些想法:
可以实施吗?或者有没有其他类似结果的解决方案?
我想知道ARM Cortex-M4内部是否有缓存。
我在技术参考手册中没有找到任何线索,但这是官方的还是隐藏的?我知道有些微控制器有缓存,但它位于总线和 RAM 之间,而不是内核内部。
你知道有什么文件可以澄清这一点吗?
我尝试遵循“自然对数 (ln) 和指数的有效实现”主题,以便能够在没有 math.h 的情况下实现对数函数。所描述的算法对于 1 到 2 之间的值(标准化值)效果很好。但是,如果这些值未标准化并且我遵循标准化说明,那么我会得到错误的值。
链接:点击这里
如果我按照示例整数值 12510 执行代码,我会得到以下结果:
y = 12510 (0x30DE),log2 = 13,除数 = 26,x = 481,1538
float ln(float y) {
int log2;
float divisor, x, result;
log2 = msb((int)y); // See: /sf/answers/347960161/
divisor = (float)(1 << log2);
x = y / divisor; // normalized value between [1.0, 2.0]
result = -1.7417939 + (2.8212026 + (-1.4699568 + (0.44717955 - 0.056570851 * x) * x) * x) * x;
result += ((float)log2) * 0.69314718; …Run Code Online (Sandbox Code Playgroud) 一些微控制器(例如 ATtiny12)根本没有 SRAM。怎么可能让他们做任何有用的事情?为什么会有人制造如此有限的设备?
我能想到的对没有 RAM 的芯片进行编程的唯一方法是使用某种原始状态机,其中程序计数器的当前值本质上定义了状态。例如:
Do
Wait for button press
Illuminate the LED
Wait for button release
Extinguish the LED
Loop
Run Code Online (Sandbox Code Playgroud)
我不是要解决特定问题,我只是好奇。没有内存可以实现更复杂的东西吗?我试过谷歌搜索,没有有用的结果。
我在这里错过了什么吗?
微控制器负责采样 ADC 值(模数转换)。由于这些部分受容差和噪声的影响,因此可以通过删除 4 个最差值来显着提高精度。查找和删除确实需要时间,这并不理想,因为它会增加循环时间。
想象一下 100MHz 的频率,所以软件的每个命令确实需要 10ns 来处理,命令越多,控制器被阻止执行下一组样本的时间就越长
所以我的目标是尽可能快地完成排序过程,我目前使用这个代码,但这只会删除最糟糕的两个!
uint16_t getValue(void){
adcval[8] = {};
uint16_t min = 16383 //14bit full
uint16_t max = 1; //zero is physically almost impossible!
uint32_t sum = 0; //variable for the summing
for(uint8_t i=0; i<8;i++){
if(adc[i] > max) max = adc[i];
if(adc[i] < min) min = adc[i];
sum=sum+adcval[i];
}
uint16_t result = (sum-max-min)/6; //remove two worst and divide by 6
return result;
}
Run Code Online (Sandbox Code Playgroud)
现在我想扩展这个函数以删除 8 个样本中的 4 个最差值以获得更高的精度。关于如何做到这一点的任何建议?
此外,构建一个高效的函数来查找偏差最大的值,而不是最高和最低值,这将是很棒的。例如,想象这两个数组
uint16_t adc1[8] {5,6,10,11,11,12,20,22};
uint16_t …Run Code Online (Sandbox Code Playgroud) 我是微控制器的新手。我已经阅读了很多关于volatilec 中变量的文章和文档。我的理解是,在使用时volatile我们告诉编译器不要cache优化变量。但是我仍然没有得到真正应该使用它的时间。
例如,假设我有一个简单的计数器和这样的 for 循环。
for(int i=0; i < blabla.length; i++) {
//code here
}
Run Code Online (Sandbox Code Playgroud)
或者当我写这样一段简单的代码时
int i=1;
int j=1;
printf("the sum is: %d\n" i+j);
Run Code Online (Sandbox Code Playgroud)
我从不关心此类示例的编译器优化。但是在许多范围内,如果变量未声明为volatile输出,则不会如预期的那样。我怎么知道我必须关心其他示例中的编译器优化?
我正在使用 STM32 G474 用它的内部 DAC 创建一个 wavefrom。我为直接内存访问 (DMA) 模块提供了一个查找表,并在正确的时间将值提供给相应的 DAC 通道。听起来困难的部分实际上非常简单并且工作得很好。
#define NS 64 # number of samples
uint32_t Wave_Low[NS] = {2048,[...],2047}; # lookup table
int main(void)
{
HAL_DAC_Start_DMA( &hdac2, DAC_CHANNEL_1, (uint32_t*)Wave_High, NS, DAC_ALIGN_12B_R);
*/ start DMA use DAC2 channel 1 */
}
Run Code Online (Sandbox Code Playgroud)
作为下一步,我想更改代码中的信号形式。因为我希望这不会中断,所以停止 DMA 并重新初始化它不起作用(有 500 微秒的延迟,中间没有信号)。因此我需要覆盖查找表。我试过这样:
#define NS 64 # number of samples
uint32_t Wave_Low[NS] = {2048,[...],2047}; # lookup table 1
uint32_t Wave_High[NS] = {4096,[...],4067}; # lookup table 2
uint32_t Wave_Active[NS]; #used lookup table
int main(void)
{
memcpy(Wave_Active …Run Code Online (Sandbox Code Playgroud)