USB VCP printf function

#define USB_PRINTF_BUF_SIZE 64
char usbTxBuf[USB_PRINTF_BUF_SIZE];
void usb_printf (const char* format,…)
{
//uint32_t length;
va_list args;
va_start(args, format);
vsnprintf((char *)usbTxBuf, sizeof(usbTxBuf), (char *)format, args);
va_end(args);
CDC_Transmit_FS((uint8_t *)usbTxBuf, strlen(usbTxBuf));
}

廣告

STM32F4xx SPI configuration

Concerning SCK clock signal, the user has to respect fixed clock phase and polarity
between communicating nodes. Four possible timing relationships may be chosen by
software, using CPOL (clock polarity) and CPHA (clock phase) parameters.
The CPOL parameter controls the steady state value of the clock when no data is being
transferred. This parameter affects both master and slave modes. If CPOL is low, the SCK
pin has a low-level idle state. If CPOL is high, the SCK pin has a high-level idle state.
If the CPHA parameter is configured as 1EDGE, the first edge on the SCK pin (rising edge if
CPOL is low, falling edge if CPOL is high) is the MSBit capture strobe. Data are latched on
the occurrence of the first clock transition.

If the CPHA parameter is configured as 2EDGE, the second edge on the SCK pin (rising
edge if CPOL is high, falling edge if CPOL is low) is the MSBit capture strobe. Data are
latched on the occurrence of the second clock transition.
The combination of the CPOL and CPHA parameter selects the data capture clock edge
(see Table 2).

table2
Figure 2 shows an SPI transfer with the four combinations of the CPHA and CPOL. The
diagram may be interpreted as a master or slave timing diagram where the SCK pin, the
MISO pin, the MOSI pins are directly connected between the master and the slave device.

figure2

Benchmarking Raspberry Pi GPIO Speed

Method and Summary of Results

The basic test setup was to toggle one of the GPIO pins between zero and one as fast as possible. GPIO 4 was selected due to easy access and no overlapping functionality. This is basically the “upper limit” for any signalling one can hope to achieve with the GPIO pins – real-life scenarios where processing needs to be done would need to aim for some fraction of these values. Here are the current results:

Language Library Tested / version Square wave
Shell /proc/mem access 2015-02-14 2.8 kHz
Shell / gpio utility WiringPi gpio utility 2015-02-15 / 2.25 40 Hz
Python RPi.GPIO 2015-02-15 / 0.5.10 70 kHz
Python wiringpi2 bindings 2015-02-15 / latest github 28 kHz
Ruby wiringpi bindings 2015-02-15 / latest gem (1.1.0) 21 kHz
C Native library 2015-02-15 / latest RaspPi wiki code 22 MHz
C BCM 2835 2015-02-15 / 1.38 5.4 MHz
C wiringPi 2015-02-15 / 2.25 4.1 – 4.6 MHz
Perl BCM 2835 2015-02-15 / 1.9 48 kHz

from: http://codeandlife.com/2012/07/03/benchmarking-raspberry-pi-gpio-speed/

 

C queue with struct

#include
#include

#define MAX_LEN_PARAMS 10
struct Command
{
char id;
char length;
char params[MAX_LEN_PARAMS];
char checksum;
};

struct CommandQueue
{
struct Command data;
struct CommandQueue *next;
};

// Two glboal variables to store address of front and rear nodes.
static CommandQueue *front = NULL;
static CommandQueue *rear = NULL;

void cmd_enqueue (struct Command cmd)
{
struct CommandQueue *q = (struct CommandQueue*)malloc (sizeof (struct CommandQueue));
q->data = cmd;
q->next = NULL;
if (front == NULL && rear == NULL)
{
front = rear = q;
return;
}
rear->next = q;
rear = q;
}

void cmd_dequeue ()
{
struct CommandQueue *temp = front;
if (front == NULL)
{
printf (“ERROR: the queue is emprt\r\n");
return;
}
if (front == rear)
{
front = rear = NULL;
}
else
{
front = front->next;
}
free (temp);
}

struct Command cmd_front ()
{
if (front == NULL)
{
struct Command ce;
ce.id = 255;
printf (“ERROR: queue is empty");
return ce;
}
return front->data;
}

void cmd_print ()
{
struct CommandQueue *temp = front;
while (temp != NULL)
{
printf (“%d “, temp->data.id);
temp = temp->next;
}
printf (“\r\n");
}

int main (void)
{
struct Command c1;
c1.id = 1;

struct Command c2;
c2.id = 2;

struct Command c3;
c3.id = 3;

struct Command c4;
c4.id = 4;

struct Command c5;
c5.id = 5;

cmd_enqueue (c1); cmd_print();
cmd_enqueue (c2); cmd_print();
cmd_enqueue (c3); cmd_print();
cmd_dequeue();
struct Command cc1 = cmd_front();
printf (“cc1 id=%d\r\n", cc1.id);
cmd_enqueue (c5); cmd_print();
return 1;
}

ARM Interrupt Latency

ARM Interrupt Latency

The interrupt latency of all of the Cortex-M processors is extremely low. The latency count is listed in table 1, and is the exact number of cycles from the assertion of the interrupt request up to the cycle where the first instruction of the interrupt handler is ready to be expected, in a system with zero wait state memory systems:

Processors Cycles with zero wait state memory
Cortex-M0 16
Cortex-M0+ 15
Cortex-M3 12
Cortex-M4 12
Table 1: Interrupt latency of Cortex-M processors with zero wait state memory systems

步進電機半流全流

电流是电机运行的载体,但电压的高低也直接影响到电流,很多人使用步进电机存在误区,认为半流的作用是减小发热。其实半流是节约电能考虑的。低劣而发热的电机,能耗本来就高,一定要通过静态半流来控制电机的发热。好的电机发热本来就小(当然连续高速不间断运行还是会发热,但半流就没有意义了),何况电机静止和运行能耗一样高的产品,肯定会考虑降低能耗。
步进电机半流的运用:1:物体给步进电机反作用力较小的设备(大部分是这样结构),请用半流,甚至使能电机。
反作用力需要步进电机自锁才能定位的结构,请选择全流。(例:上下传动结构)
衰减电流设置一般没有多大意义。
很多驱动器都有自动衰减电流(自动内部调节,和保护电路),只有一些老款的驱动才有。
其实、任何电器元件的电流都有衰减过程。只不过,其它元器件的衰减过程是瞬间完成的,所以被忽略了。而电感的特性就是有阻止电路改变的能力,也就是说,电感中的电流不能瞬间改变,所以,有一个衰减的过程。其原理是由于电流变化是电感线圈中的磁通发生改变,磁通的变化又在线圈中产生了电动势,这个电动势的方向恰好是阻止电流变化的方向,也就是说,当电流变大时,电动势与电流方向相反,起减小电流的作用;电流变小时,电动势方向与电流方向相同,其加强电流的作用。由于这个电动势的存在,电感才有衰减电流的过程。而在电路设计中,也都要设置相应的保护措施,以保证在断电过程中,能够使电感顺利完成这个过程,不至于产生瞬间大电流损坏电路。

所谓步进电机半流设置是指,当你需要步进电机工作时,它是全流工作,而你不需要它动作时,为了保持因为外力导致步进电机发生扭动或者转动。需要设置它少量的电流维系您的力矩平衡,这个根据实际情况设置相应的力度即可,而衰减的意思是,从最高力矩到最低力矩的时间或者衰减方式。为了使你的机械运行平衡,不是冲击性或者突然性刹车使用的。希望您可以理解。

半流就是说电机停止时,定子锁住转子的力会下降为一半,可以减少电机的发热量和节能。

HAL printf function

by default HAL not override the printf() function, the following code re-direct the printf() to usart.

#ifdef __GNUC__
/* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf
set to ‘Yes’) calls __io_putchar() */
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif /* __GNUC__ */

/**
* @brief Retargets the C library printf function to the USART.
* @param None
* @retval None
*/
PUTCHAR_PROTOTYPE
{
/* Place your implementation of fputc here */
/* e.g. write a character to the USART */
HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 100);
return ch;
}