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(); //读串口数据,串口上第 ...
随机推荐
- ZEDBOARD启动自启配置(加载镜像) 分类: OpenCV ubuntu shell ZedBoard Eye_Detection 2014-11-08 18:53 167人阅读 评论(0) 收藏
参考:陆书14.2.8 1)备份ramdisk8M.image.gz 2)加载rootfs镜像文件: 3)在镜像目录下建立自己所需文件夹(挂载目录): 我需要的挂载目录有两个: root/qt/ins ...
- GDB技巧整理
https://blog.atime.me/note/gdb-tricks.html 整理常用的gdb技巧. 常用命令 常用的gdb命令... 启动gdb 直接运行 gdb --args prog a ...
- tcp ip参数详解
http://www.cnblogs.com/digdeep/p/4869010.html 1. TCP/IP模型 我们一般知道OSI的网络参考模型是分为7层:“应表会传网数物”——应用层,表示层,会 ...
- 关于C++的疑问剖析
1)众所周知,抽象类是不存在对象的,只提供接口而不提供实现.但是抽象类能不能作为一个类指针,指向其子类的对象呢? class Interface { public: ; }; class Implem ...
- 规范javascript书写
空白 缩进 换行限制 if while for do 2. 命名 常量 URL_CONFIG 变量 listLen 函数命名 调用函数 function setStyle(dom, name, v ...
- ios里面如何压缩图片
在iOS里面,压缩图片跟在其他环境里面差不多,都和累死, 就是对当前图片从新画图,制定一个尺寸的问题 UIImage* image = [UIImage imageNamed:@"cat.j ...
- Codeforces 543C Remembering Strings(DP)
题意比较麻烦 见题目链接 Solution: 非常值得注意的一点是题目给出的范围只有20,而众所周知字母表里有26个字母.于是显然对一个字母进行变换后是不影响到其它字符串的. 20的范围恰好又是常见状 ...
- IO流基础
IO流,也称为数据流,用于处理设备之间的数据传输. JAVA对数据的操作就是通过流的方式,而流分为两种:字符流,字节流 字符流: 可以内部制定码表,处理文字很方便,字符流里的基类是Reader,Wri ...
- jQuery慢慢啃之属性(三)
1.attr(name|properties|key,value|fn)设置或返回被选元素的属性值. $("img").attr("src");//获取属性 $ ...
- 验证视图状态MAC失败解决方案
验证视图状态 mac 失败.如果此应用程序由网络场或群集承载 请确保 machinekey 配置指定了相同的 validationkey 和验证算法.不能在群集中使用 autogenerate. 总是 ...