我们有一个简单的架构:
PIC通过基于中断的I2C通信协议与ARM通信以传输数据.在中断内部,我们发出一个从I2C层(总线)读取数据的任务.
在数据有限的情况下,我们通常不会有太多问题来读取数据并将其发送到上层.如果这个数据非常庞大,中断将被连接很长时间.
第一个问题是:
我对吗?
如果我是对的,如何避免相同?......或者我们可以采用不同的方案吗?
我有以下代码
try{
sleep(500);
}catch(InterruptedException e){}
Run Code Online (Sandbox Code Playgroud)
是InterruptedException当线程完成睡觉时或抛出interrupt方法被调用的线程?
我做了一个计数器应用程序,当用户在控制台中输入"stop"时,它使用线程来中断计数.我仔细检查了我的代码,我看不出问题.我是新手,所以任何人都可以看看这个.
import java.util.Scanner;
public class CounterInterruptApp
{
public static void main(String[] args)
{
new CounterInterruptApp().start();
}
public void start()
{
Thread counter = new Counter(); //Instantiate the counter thread.
counter.start(); //Start the counter thread.
Scanner scanner = new Scanner(System.in);
String s = "";
while(!s.equals("stop")); //Wait for the user to enter stop.
s=scanner.next();
counter.interrupt(); //Interrupt the counter thread.
}
}
public class Counter extends Thread //Extend Thread for the use of the Thread Interface.
{
public void run()//Run method. This is …Run Code Online (Sandbox Code Playgroud) 从设置线程状态的角度来看,我不清楚这两种方法.
Java Docs说Thread.interrupt()设置线程中断状态标志并调用Thread.interrupted()方法给出线程的状态并清除标志.
当这在真实场景中使用时.. ??
从我读到的,我的问题的解决方案是使用中断,但如果我正确理解它,我不能在中断调用的例程中使用延迟.我有一个大按钮LED开关.我希望它在闲置时有一个心跳,但一旦它被按下,保持绿色并执行代码.
heartbeat()如果我按下按钮足够的次数,我可以打破(我假设在正确的时间完成状态更改,因为它完成了循环heartbeat),但我仍然坚持如何使它在第一次点击时工作.有没有其他方法来做我正在尝试的事情?
void loop(){
heartbeat(); //Make LED beat.
buttonVal = digitalRead(buttonPin); //Check the button.
if (buttonVal != buttonState) { //If the button state changed.
if (buttonVal == HIGH){ //Check if the button is pressed.
analogWrite(greenPin, 255); //Button stays green once pushed.
functionA //Has some delays in it.
functionB //Has some other delays.
}
}
}
void heartbeat(){
for(i = 0; i < pmw; i++) {
analogWrite(greenPin,i);
delay(((60000/rate)*.1)/pmw);
}
for (i = pmw; i > 0; …Run Code Online (Sandbox Code Playgroud) 我正在查看avr-gcc小型C程序的程序集生成代码.以下应该在堆栈上分配一个100字节的本地数组.
extern void foo(char [], int);
void bar()
{
char t[100];
foo(t,100);
}
Run Code Online (Sandbox Code Playgroud)
当然它通过从堆栈指针中减去100来实现.
据我所知,由于avr是8位机器,更改16位堆栈指针需要2个步骤(更改SPH和SPL).此外,通过禁用中断来提供一些原子性是个好主意.它由序列完成
in r28,__SP_L__
in r29,__SP_H__ ; get SP
subi r28,100 ; new SP in R29:R28 = OLD -100
sbc r29,__zero_reg__
in __tmp_reg__,__SREG__ ; save status to r0
cli ; disable interrupts
out __SP_H__,r29 ; update SPH
out __SREG__,__tmp_reg__ ; restore status -- why here ?
out __SP_L__,r28 ; update SPL
Run Code Online (Sandbox Code Playgroud)
我还不相信恢复状态指令的位置.
为什么在更新SPL后没有完成?
也许保证在(重新)启用中断后,在下一条指令完成之前不会将中断记入账户?
根据我的理解,当触发软件中断时,系统调用会得到服务,因此我认为它不能中断硬件ISR,因为ISR内部的本地CPU irq被禁用,但它看起来可能会中断任何其他任务,例如softirq,tasklet ,工作队列和内核线程?
通常,我们不需要担心在优先级较高的任务中针对较低优先级内核任务的争用.就像我们不需要保护数据免受tasklet或softirq中的内核线程,因为抢占被禁用.
当系统调用在内核模式的进程上下文中运行时,如果它可以中断softirq,我们必须在针对进程的softirq中考虑适当的保护.更糟糕的是,重负载系统调用可以延迟执行softirqs和tasklet至少一次滴答或直到另一个硬件中断到来并且内核再次调度它们.
如果我的理解是错误的,请纠正我.
我有一个STM32F302CBT6(运行在72MHz)项目,我需要测量4个信号的频率,每个信号约250kHz.信号连接到TIM1通道1-4.
现在,了解250kHz太快(或者是?)同时处理所有那些输入捕获中断(因为它们可能同步或同时发生......)我想逐个测量每个通道.我在程序开始时初始化了所有通道,并考虑在每个通道测量后逐个启用相应的中断.这是一个合适的想法还是我错过了什么?
问题是在为通道1提供第一个中断之后,下一个中断从未得到服务,因为虽然没有使能中断,但状态寄存器还有多个其他待处理中断(CCxIF和CCXOF,以及CxIF)以及设置的过捕获标志.我试图通过读取所有捕获值或设置TIMx-> SR = 0但没有帮助来避免此问题.
我将如何测量这些信号以及确保正确捕获每个通道的正确方法是什么?
我对此非常感兴趣,并希望了解如何进行这种处理或者如果你能指出我做错了什么.谢谢.
我目前的相关代码如下.
这是中断处理程序:
void TIM1_CC_IRQHandler(void) {
if (TIM_GetITStatus(IC_TIMER, IC_CH1) == SET) {
/* Clear TIM1 Capture compare interrupt pending bit */
TIM_ClearITPendingBit(IC_TIMER, IC_CH1);
//Read the capture value
raw_captures[capture_index] = TIM_GetCapture1(IC_TIMER);
capture_index++;
//Also read the others to avoid overcaptures
TIM_GetCapture2(IC_TIMER);
TIM_GetCapture3(IC_TIMER);
TIM_GetCapture4(IC_TIMER);
if(capture_index == 2) {
TIM_ITConfig(IC_TIMER, IC_CH1, DISABLE);
}
} else if (TIM_GetITStatus(IC_TIMER, IC_CH2 == SET)) {
TIM_ClearITPendingBit(IC_TIMER, IC_CH2);
//Read the capture value
raw_captures[capture_index] = TIM_GetCapture2(IC_TIMER);
capture_index++;
TIM_GetCapture1(IC_TIMER);
TIM_GetCapture3(IC_TIMER);
TIM_GetCapture4(IC_TIMER);
if(capture_index == 4) …Run Code Online (Sandbox Code Playgroud) 我目前正在开发一个更大的Arduino Mega 2560项目; 涉及伺服控制和传感器读数.我正在使用超声波接近传感器(HC-SR04)和NewPing 1.8库,该库使用中断来检测传感器的回声.此外,我还阅读了温度和光强度测量.通过使用cmdMessenger3库,从HC-SR04超声波传感器接收的距离数据通过USB转发到主机.伺服系统由来自主机的消息使用标准伺服库控制.
一旦NewPing库调用ISR检测到超声回波的时间,就会开始乱七八糟.当距离数据可用时,这是NewPing库调用的函数:
void sendSonarData(uint8_t sensorId, uint16_t distance) {
//noInterrupts();
cmdMsg3.sendCmdStart(kReadSonar);
cmdMsg3.sendCmdArg(sensorId);
cmdMsg3.sendCmdArg(distance);
cmdMsg3.sendCmdEnd();
//interrupts();
}
Run Code Online (Sandbox Code Playgroud)
这是另一个回调函数,它通过cmdMessenger3库将温度数据发送到主机:
void sendTemperatureData(uint8_t sensorId, uint16_t temperature) {
//noInterrupts();
cmdMsg3.sendCmdStart(kReadTemperature);
cmdMsg3.sendCmdArg(sensorId);
cmdMsg3.sendCmdArg(temperature);
cmdMsg3.sendCmdEnd();
//interrupts();
}
Run Code Online (Sandbox Code Playgroud)
问题:当Arduino试图发送温度数据时,来自超声波传感器的ISR可能会跳入并将其自己的数据写入串行流; 关于发送到主机的串行数据一团糟,因为发送过程不是原子的,由多个命令组成,用于发送一条消息(sendCmdStart- > sendCmdArg- > sendCmdEnd).
这是一个例子:
sendTemperatureData(...)称为温度cmdMsg3.sendCmdStart(kReadTemperature); 叫做cmdMsg3.sendCmdArg(sensorId); 叫做sendTemperatureData(); 叫做cmdMsg3.sendCmdStart(kReadSonar); 叫做cmdMsg3.sendCmdArg(sensorId);cmdMsg3.sendCmdArg(distance);cmdMsg3.sendCmdEnd();sendTemperatureData(...)被称为cmdMsg3.sendCmdArg(temperature);cmdMsg3.sendCmdEnd();然后,我试图通过使用在发送过程中阻止ISR调用noInterrupts()/interrupts(); 使发送过程有点'原子'.但这导致了许多其他问题,millis()/micros()功能不再精确,串行通信发生故障等; 所有都依赖于被禁用的计时器 …
测试使用中断的代码,我强迫使用a while(1);尝试保留在中断处理程序中,但是我看到中断处理程序离开并返回到main,因此我假设它具有某种超时。如果是这样,它是ISR所特有的,还是中断的标准功能?