STM32F10x 学习笔记6(USART实现串口通讯 2)
这次讲讲利用串口收发中断来进行串口通讯。STM32 上为每个串口分配了一个中断。也就是说无论是发送完成还是收到数据或是数据溢出都产生同一个中断。程序需在中断处理函数中读取状态寄存器(USART_SR)来判断当前的是什么中断。下面的中断映像图给出了这些中断源是如何汇合成最终的中断信号的。图中也给出了如何控制每一个单独的中断源是否起作用。
另外,Cortex-M3 内核中还有个NVIC,可以控制这里的中断信号是否触发中断处理函数的执行,还有这些外部中断的级别。关于NVIC 可以参考《ARM CortexM3 权威指南》,里面讲解的非常详细。
简单的说,为了开启中断,我们需要如下的代码:
NVIC_InitTypeDef NVIC_InitStructure; NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = ; NVIC_InitStructure.NVIC_IRQChannelSubPriority = ; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); //开启接收中断 USART_ITConfig(USART1, USART_IT_TXE, ENABLE); // 开启发送中断
这里多说一句,串口的发送中断有两个,分别是:
- l发送数据寄存器空中断(TXE)
- l发送完成中断(TC)
一般来说我们会使用发送数据寄存器空中断,用这个中断发送的效率会高一些。
中断处理函数的框架如下,如果检测到错误就清除错误,收到数了就处理。发完当前数据了就发下一个。
void USART1_IRQHandler(void)
{
unsigned int data;
if(USART1->SR & 0x0F)
{
// See if we have some kind of error, Clear interrupt
data = USART1->DR;
}
else if(USART1->SR & USART_FLAG_RXNE) //Receive Data Reg Full Flag
{
data = USART1->DR;
// 对收到的数据进行处理,或者干些其他的事
}
else if(USART1->SR & USART_FLAG_TXE)
{
{ // 可以发送数据了,如果没有数据需要发送,就在这里关闭发送中断
USART1->DR = something; // Yes, Send character
}
}
}
下面给一个利用环形缓冲区的串口驱动程序。
#ifndef _COM_BUFFERED_H_ #define _COM_BUFFERED_H_ #define COM1 0 #define COM2 1 #define COM_RX_BUF_SIZE 64 /* Number of characters in Rx ring buffer */ #define COM_TX_BUF_SIZE 64 /* Number of characters in Tx ring buffer */ #define COM_NO_ERR 0 /* Function call was successful */ #define COM_BAD_CH 1 /* Invalid communications port channel */ #define COM_RX_EMPTY 2 /* Rx buffer is empty, no character available */ #define COM_TX_FULL 3 /* Tx buffer is full, could not deposit character */ #define COM_TX_EMPTY 4 /* If the Tx buffer is empty. */ /************************************************************ * function : COMGetCharB * parameter: char port, port can be COM1 / COM2 * parameter: char* err is a pointer to where an error code will be placed: * *err is set to COM_NO_ERR if a character is available * *err is set to COM_RX_EMPTY if the Rx buffer is empty * *err is set to COM_BAD_CH if you have specified an invalid channel * return : char * usage : This function is called by your application to obtain a character from the communications * channel. * changelog: *************************************************************/ unsigned char COMGetCharB (unsigned char ch, unsigned char *err); /************************************************************ * function : COMPutCharB * parameter: char port, port can be COM1 / COM2 * return : COMM_NO_ERR if the function was successful (the buffer was not full) * COMM_TX_FULL if the buffer was full * COMM_BAD_CH if you have specified an incorrect channel * usage : This function is called by your application to send a character on the communications * channel. The character to send is first inserted into the Tx buffer and will be sent by * the Tx ISR. If this is the first character placed into the buffer, the Tx ISR will be * enabled. If the Tx buffer is full, the character will not be sent (i.e. it will be lost) * changelog: *************************************************************/ unsigned char COMPutCharB (unsigned char port, unsigned char c); /************************************************************ * function : COMBufferInit * parameter: * return : * usage : This function is called by your application to initialize the communications module. You * must call this function before calling any other functions. * changelog: *************************************************************/ void COMBufferInit (void); /************************************************************ * function : COMBufferIsEmpty * parameter: char port, port can be COM1 / COM2 * return : char * usage : This function is called by your application to see * if any character is available from the communications channel. * If at least one character is available, the function returns * FALSE(0) otherwise, the function returns TRUE(1). * changelog: *************************************************************/ unsigned char COMBufferIsEmpty (unsigned char port); /************************************************************ * function : COMBufferIsFull * parameter: char port, port can be COM1 / COM2 * return : char * usage : This function is called by your application to see if any more characters can be placed * in the Tx buffer. In other words, this function check to see if the Tx buffer is full. * If the buffer is full, the function returns TRUE otherwise, the function returns FALSE. * changelog: *************************************************************/ unsigned char COMBufferIsFull (unsigned char port); #endif
/*
* file: com_buffered.c
* author: Li Yuan
* platform: STM32F107
* date: 2013-5-5
* version: 0.0.1
* description: UART Ring Buffer
**/
#include "stm32f10x_usart.h"
#include "com_buffered.h"
#define OS_ENTER_CRITICAL() __set_PRIMASK(1)
#define OS_EXIT_CRITICAL() __set_PRIMASK(0)
/**
* Enables Transmiter interrupt.
**/
static void COMEnableTxInt(unsigned char port)
{
] = {USART1, USART2};
USART_ITConfig(map[port], USART_IT_TXE, ENABLE);
}
/*
*********************************************************************************************************
* DATA TYPES
*********************************************************************************************************
*/
typedef struct {
short RingBufRxCtr; /* Number of characters in the Rx ring buffer */
unsigned char *RingBufRxInPtr; /* Pointer to where next character will be inserted */
unsigned char *RingBufRxOutPtr; /* Pointer from where next character will be extracted */
unsigned char RingBufRx[COM_RX_BUF_SIZE]; /* Ring buffer character storage (Rx) */
short RingBufTxCtr; /* Number of characters in the Tx ring buffer */
unsigned char *RingBufTxInPtr; /* Pointer to where next character will be inserted */
unsigned char *RingBufTxOutPtr; /* Pointer from where next character will be extracted */
unsigned char RingBufTx[COM_TX_BUF_SIZE]; /* Ring buffer character storage (Tx) */
} COM_RING_BUF;
/*
*********************************************************************************************************
* GLOBAL VARIABLES
*********************************************************************************************************
*/
COM_RING_BUF COM1Buf;
COM_RING_BUF COM2Buf;
/************************************************************
* function : COMGetCharB
* parameter: char port, port can be COM1 / COM2
* parameter: char* err is a pointer to where an error code will be placed:
* *err is set to COM_NO_ERR if a character is available
* *err is set to COM_RX_EMPTY if the Rx buffer is empty
* *err is set to COM_BAD_CH if you have specified an invalid channel
* return : char
* usage : This function is called by your application to obtain a character from the communications
* channel.
* changelog:
*************************************************************/
unsigned char COMGetCharB (unsigned char port, unsigned char *err)
{
// unsigned char cpu_sr;
unsigned char c;
COM_RING_BUF *pbuf;
switch (port)
{ /* Obtain pointer to communications channel */
case COM1:
pbuf = &COM1Buf;
break;
case COM2:
pbuf = &COM2Buf;
break;
default:
*err = COM_BAD_CH;
);
}
OS_ENTER_CRITICAL();
) /* See if buffer is empty */
{
pbuf->RingBufRxCtr--; /* No, decrement character count */
c = *pbuf->RingBufRxOutPtr++; /* Get character from buffer */
if (pbuf->RingBufRxOutPtr == &pbuf->RingBufRx[COM_RX_BUF_SIZE])
{
pbuf->RingBufRxOutPtr = &pbuf->RingBufRx[]; /* Wrap OUT pointer */
}
OS_EXIT_CRITICAL();
*err = COM_NO_ERR;
return (c);
} else {
OS_EXIT_CRITICAL();
*err = COM_RX_EMPTY;
c = ; /* Buffer is empty, return 0 */
return (c);
}
}
/************************************************************
* function : COMPutCharB
* parameter: char port, port can be COM1 / COM2
* return : COMM_NO_ERR if the function was successful (the buffer was not full)
* COMM_TX_FULL if the buffer was full
* COMM_BAD_CH if you have specified an incorrect channel
* usage : This function is called by your application to send a character on the communications
* channel. The character to send is first inserted into the Tx buffer and will be sent by
* the Tx ISR. If this is the first character placed into the buffer, the Tx ISR will be
* enabled. If the Tx buffer is full, the character will not be sent (i.e. it will be lost)
* changelog:
* 1.first implimented by liyuan 2010.11.5
*************************************************************/
unsigned char COMPutCharB (unsigned char port, unsigned char c)
{
// unsigned char cpu_sr;
COM_RING_BUF *pbuf;
switch (port)
{ /* Obtain pointer to communications channel */
case COM1:
pbuf = &COM1Buf;
break;
case COM2:
pbuf = &COM2Buf;
break;
default:
return (COM_BAD_CH);
}
OS_ENTER_CRITICAL();
if (pbuf->RingBufTxCtr < COM_TX_BUF_SIZE) { /* See if buffer is full */
pbuf->RingBufTxCtr++; /* No, increment character count */
*pbuf->RingBufTxInPtr++ = c; /* Put character into buffer */
if (pbuf->RingBufTxInPtr == &pbuf->RingBufTx[COM_TX_BUF_SIZE]) { /* Wrap IN pointer */
pbuf->RingBufTxInPtr = &pbuf->RingBufTx[];
}
) { /* See if this is the first character */
COMEnableTxInt(port); /* Yes, Enable Tx interrupts */
OS_EXIT_CRITICAL();
} else {
OS_EXIT_CRITICAL();
}
return (COM_NO_ERR);
} else {
OS_EXIT_CRITICAL();
return (COM_TX_FULL);
}
}
/************************************************************
* function : COMBufferInit
* parameter:
* return :
* usage : This function is called by your application to initialize the communications module. You
* must call this function before calling any other functions.
* changelog:
*************************************************************/
void COMBufferInit (void)
{
COM_RING_BUF *pbuf;
pbuf = &COM1Buf; /* Initialize the ring buffer for COM0 */
pbuf->RingBufRxCtr = ;
pbuf->RingBufRxInPtr = &pbuf->RingBufRx[];
pbuf->RingBufRxOutPtr = &pbuf->RingBufRx[];
pbuf->RingBufTxCtr = ;
pbuf->RingBufTxInPtr = &pbuf->RingBufTx[];
pbuf->RingBufTxOutPtr = &pbuf->RingBufTx[];
pbuf = &COM2Buf; /* Initialize the ring buffer for COM1 */
pbuf->RingBufRxCtr = ;
pbuf->RingBufRxInPtr = &pbuf->RingBufRx[];
pbuf->RingBufRxOutPtr = &pbuf->RingBufRx[];
pbuf->RingBufTxCtr = ;
pbuf->RingBufTxInPtr = &pbuf->RingBufTx[];
pbuf->RingBufTxOutPtr = &pbuf->RingBufTx[];
}
/************************************************************
* function : COMBufferIsEmpty
* parameter: char port, port can be COM1 / COM2
* return : char
* usage : This function is called by your application to see
* if any character is available from the communications channel.
* If at least one character is available, the function returns
* FALSE(0) otherwise, the function returns TRUE(1).
* changelog:
*************************************************************/
unsigned char COMBufferIsEmpty (unsigned char port)
{
// unsigned char cpu_sr;
unsigned char empty;
COM_RING_BUF *pbuf;
switch (port)
{ /* Obtain pointer to communications channel */
case COM1:
pbuf = &COM1Buf;
break;
case COM2:
pbuf = &COM2Buf;
break;
default:
);
}
OS_ENTER_CRITICAL();
)
{ /* See if buffer is empty */
empty = ; /* Buffer is NOT empty */
}
else
{
empty = ; /* Buffer is empty */
}
OS_EXIT_CRITICAL();
return (empty);
}
/************************************************************
* function : COMBufferIsFull
* parameter: char port, port can be COM1 / COM2
* return : char
* usage : This function is called by your application to see if any more characters can be placed
* in the Tx buffer. In other words, this function check to see if the Tx buffer is full.
* If the buffer is full, the function returns TRUE otherwise, the function returns FALSE.
* changelog:
*************************************************************/
unsigned char COMBufferIsFull (unsigned char port)
{
// unsigned char cpu_sr;
char full;
COM_RING_BUF *pbuf;
switch (port)
{ /* Obtain pointer to communications channel */
case COM1:
pbuf = &COM1Buf;
break;
case COM2:
pbuf = &COM2Buf;
break;
default:
);
}
OS_ENTER_CRITICAL();
if (pbuf->RingBufTxCtr < COM_TX_BUF_SIZE) { /* See if buffer is full */
full = ; /* Buffer is NOT full */
} else {
full = ; /* Buffer is full */
}
OS_EXIT_CRITICAL();
return (full);
}
// This function is called by the Rx ISR to insert a character into the receive ring buffer.
static void COMPutRxChar (unsigned char port, unsigned char c)
{
COM_RING_BUF *pbuf;
switch (port)
{ /* Obtain pointer to communications channel */
case COM1:
pbuf = &COM1Buf;
break;
case COM2:
pbuf = &COM2Buf;
break;
default:
return;
}
if (pbuf->RingBufRxCtr < COM_RX_BUF_SIZE) { /* See if buffer is full */
pbuf->RingBufRxCtr++; /* No, increment character count */
*pbuf->RingBufRxInPtr++ = c; /* Put character into buffer */
if (pbuf->RingBufRxInPtr == &pbuf->RingBufRx[COM_RX_BUF_SIZE]) { /* Wrap IN pointer */
pbuf->RingBufRxInPtr = &pbuf->RingBufRx[];
}
}
}
// This function is called by the Tx ISR to extract the next character from the Tx buffer.
// The function returns FALSE if the buffer is empty after the character is extracted from
// the buffer. This is done to signal the Tx ISR to disable interrupts because this is the
// last character to send.
static unsigned char COMGetTxChar (unsigned char port, unsigned char *err)
{
unsigned char c;
COM_RING_BUF *pbuf;
switch (port)
{ /* Obtain pointer to communications channel */
case COM1:
pbuf = &COM1Buf;
break;
case COM2:
pbuf = &COM2Buf;
break;
default:
*err = COM_BAD_CH;
);
}
) { /* See if buffer is empty */
pbuf->RingBufTxCtr--; /* No, decrement character count */
c = *pbuf->RingBufTxOutPtr++; /* Get character from buffer */
if (pbuf->RingBufTxOutPtr == &pbuf->RingBufTx[COM_TX_BUF_SIZE])
{
pbuf->RingBufTxOutPtr = &pbuf->RingBufTx[]; /* Wrap OUT pointer */
}
*err = COM_NO_ERR;
return (c); /* Characters are still available */
} else {
*err = COM_TX_EMPTY;
); /* Buffer is empty */
}
}
void USART1_IRQHandler(void)
{
unsigned int data;
unsigned char err;
if(USART1->SR & 0x0F)
{
// See if we have some kind of error
// Clear interrupt (do nothing about it!)
data = USART1->DR;
}
else if(USART1->SR & USART_FLAG_RXNE) //Receive Data Reg Full Flag
{
data = USART1->DR;
COMPutRxChar(COM1, data); // Insert received character into buffer
}
else if(USART1->SR & USART_FLAG_TXE)
{
data = COMGetTxChar(COM1, &err); // Get next character to send.
if (err == COM_TX_EMPTY)
{ // Do we have anymore characters to send ?
// No, Disable Tx interrupts
//USART_ITConfig(USART1, USART_IT_TXE| USART_IT_TC, ENABLE);
USART1->CR1 &= ~USART_FLAG_TXE | USART_FLAG_TC;
}
else
{
USART1->DR = data; // Yes, Send character
}
}
}
void USART2_IRQHandler(void)
{
unsigned int data;
unsigned char err;
if(USART2->SR & 0x0F)
{
// See if we have some kind of error
// Clear interrupt (do nothing about it!)
data = USART2->DR;
}
else if(USART2->SR & USART_FLAG_RXNE) //Receive Data Reg Full Flag
{
data = USART2->DR;
COMPutRxChar(COM2, data); // Insert received character into buffer
}
else if(USART2->SR & USART_FLAG_TXE)
{
data = COMGetTxChar(COM2, &err); // Get next character to send.
if (err == COM_TX_EMPTY)
{ // Do we have anymore characters to send ?
// No, Disable Tx interrupts
//USART_ITConfig(USART2, USART_IT_TXE| USART_IT_TC, ENABLE);
USART2->CR1 &= ~USART_FLAG_TXE | USART_FLAG_TC;
}
else
{
USART2->DR = data; // Yes, Send character
}
}
}
下面给个例子主程序,来演示如何使用上面的串口驱动代码。
#include "misc.h"
#include "stm32f10x.h"
#include "com_buffered.h"
void UART_PutStrB (unsigned char port, uint8_t *str)
{
!= *str)
{
COMPutCharB(port, *str);
str++;
}
}
void USART1_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_USART1, ENABLE);
/* Configure USART Tx as alternate function push-pull */
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* Configure USART Rx as input floating */
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_Init(GPIOA, &GPIO_InitStructure);
USART_InitStructure.USART_BaudRate = ;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_Init(USART1, &USART_InitStructure );
USART_Cmd(USART1, ENABLE);
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = ;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = ;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
void USART2_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD | RCC_APB2Periph_AFIO, ENABLE);
/* Configure USART Tx as alternate function push-pull */
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOD, &GPIO_InitStructure);
/* Configure USART Rx as input floating */
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_Init(GPIOD, &GPIO_InitStructure);
GPIO_PinRemapConfig(GPIO_Remap_USART2, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
USART_InitStructure.USART_BaudRate = ;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_Init(USART2, &USART_InitStructure );
USART_Cmd(USART2, ENABLE);
NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = ;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = ;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
int main(void)
{
unsigned char c;
unsigned char err;
USART1_Init();
USART2_Init();
COMBufferInit();
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);
UART_PutStrB(COM1, "Hello World!\n");
for(;;)
{
c = COMGetCharB(COM1, &err);
if(err == COM_NO_ERR)
{
COMPutCharB(COM1, c);
}
}
}
STM32F10x 学习笔记6(USART实现串口通讯 2)的更多相关文章
- STM32学习笔记(四)——串口控制LED(中断方式)
目录: 一.时钟使能,包括GPIO的时钟和串口的时钟使能 二.设置引脚复用映射 三.GPIO的初始化配置,注意要设置为复用模式 四.串口参数初始化配置 五.中断分组和中断优先级配置 六.设置串口中断类 ...
- STM32F10x 学习笔记5(USART实现串口通讯 1)
STM32F10x 系列单片机中都包含了USART 模块,所谓USART,就是通用同步异步收发器.通用同步异步收发器(USART)提供了一种灵活的方法与使用工业标准NRZ异步串行数据格式的外部设备之间 ...
- ARM-LINUX学习笔记-(虚拟机linux串口终端以及USB程序下载,基于TQ2440)
昨天安装了ssh服务之后今天在windows上用xshell登陆发现登录不上,原因是使用了virtualbox的NAT模式,在NAT模式下,客户机可以很方便地上网,但是想要链接宿主机就需要打开网络地址 ...
- STM32学习笔记(二)——串口控制LED
开发板芯片:STM32F407ZGT6 PA9-USART1_TX,PA10-USART1_RX; PF9-LED0,PF10-LED1; 一.串口1配置过程(不使用串口中断): 1.使能时钟,包括G ...
- 串口(USART)通信-串口通讯协议简介
物理层:规定通讯系统中具有机械.电子功能部分的特性,确保原始数据在物理媒体的传输.其实就是硬件部分. 协议层:协议层主要规定通讯逻辑,统一收发双方的数据打包.解包标准.其实就是软件部分. 简单来说物理 ...
- STM32学习笔记(五) USART异步串行口输入输出(轮询模式)
学习是一个简单的过程,只要有善于发掘的眼睛,总能学到新知识,然而如何坚持不懈的学习却很困难,对我亦如此,生活中有太多的诱惑,最后只想说一句勿忘初心.闲话不多扯,本篇讲诉的是异步串行口的输入输出,串口在 ...
- 【STM32学习笔记】USART 硬件流控
流控的概念源于 RS232 这个标准,在 RS232 标准里面包含了串口.流控的定义.大家一定了解,RS232 中的"RS"是Recommend Standard 的缩写,即&qu ...
- CC2540开发板学习笔记(五)——串口通信
(一)串口发送 一.实验现象: 开发板实现功能发送 二.实验过程 1.PL2303 USB转串口电路图 2.串口发送 (1)查看用户手册有: UART0 对应的外部设备 IO 引脚关系为: P0_2 ...
- Arduino101学习笔记(十)—— 串口通信
//打开串口 Serial.begin(); //获取串口上可读取的数据的字节数.该数据是指已经到达并存储在接收缓存(共有64字节)中 Serial.available(); //读串口数据,串口上第 ...
随机推荐
- web socket 心跳包的实现方案
web socket 心跳包的实现方案05/30/2010 现在网络环境错综复杂,socket心跳包是获得健康强壮的连接的有效解决方案,今天,我们就在web socket中实现心跳包方案,是的,尽管我 ...
- JAVA获取随机数
在Java中我们能够使用java.util.Random类来产生一个随机数发生器.它有两种形式的构造函数,各自是Random()和Random(long seed).Random()使用当前时间即Sy ...
- A different twist on pre-compiling JSPs--reference
I’ve blogged about this topic earlier and expressed my frustrations as to how web containers don’t p ...
- ArrayBlockingQueue 源码阅读 问题(一)
今天阅读java.util.concurrent 中 ArrayBlockingQueue 的源码,发现其中有很多下面这行代码 final ReentrantLock lock = this.lock ...
- Oracle中wm_concat()的使用方法
以下两种方式使用wm_concat()的使用方法是等效的. 方法一:使用窗口函数,wm_concat支持窗口函数 select distinct classKey,className, classOr ...
- 10.8 noip模拟试题
1.花 (flower.cpp/c/pas) [问题描述] 商店里出售n种不同品种的花.为了装饰桌面,你打算买m支花回家.你觉得放两支一样的花很难看,因此每种品种的花最多买1支.求总共有几种不同的 ...
- STM32串口通信USART1转USART2问题解决
使用的是STM32f103ZET6. 1.把文件main.c和usart.c中的所有usart1换成usart2 2.查看手册得知USART2的引脚是Tx->PA2,Rx->PA3,改变u ...
- 委托、 Lambda表达式和事件——Lambda表达式
/* * 由SharpDevelop创建. * 用户: David Huang * 日期: 2015/7/30 * 时间: 16:32 */ using System; namespace Lambd ...
- spring集成 log4j + slf4j
以maven web项目为例, 首先.在pom文件引入相关依赖,如下(spring官网文档有介绍): <dependencies> <!-- spring 相关 --> < ...
- JS中escape 方法和C#中的对应
在项目中遇到js中escape过的json字符串,需要在C#中对应模拟编码,记得原来遇到过这个问题,但是当时没记录下来方案, 于是又搜索了一番,发现别人说的都是HttpUtility.UrlEncod ...