寫完這篇文章想着之後儘可能(應該說必定)使用如今正在使用的LPC系列的單片機寫程序,其實心裏感受仍是LPC作的至關完善,,,,,配置上沒有32那麼的繁瑣....c++
關於串口發送數據,本身之前呢是這樣數組
void Usart_Out_Char(unsigned char *c,uint32_t cnt) { while(cnt--) { USART_SendData(USART1, *c++); while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET ); } }
下面的調用方式緩存
uint8_t aaa[1024]={1,2,3,42,0}; int main(void) { NVIC_Configuration(); Led_Gpio_Init(); Timer2_Config(); uart_init(115200); //串口初始化爲115200while(1) { Usart_Out_Char(aaa,1024); delay_ms(1000); PFout(6) = ~PFout(6); } }
當發送數據的時候,會一直在調用此函數的地方等着,,,,,,直至發送完全部的數據,要知道用串口中斷髮送數據要比這樣發送快的多.......瞎耽誤時間數據結構
假設如今我用中斷髮送函數
假設沒有緩衝區ui
void UsartOutChar(unsigned char *Buff,uint32_t cnt) { dat = Buff;//把發送地址給dat BuffCnt = cnt;//記錄發送的個數 USART_ITConfig(USART1, USART_IT_TXE, ENABLE);//打開發送中斷 }
void USART1_IRQHandler(void) //串口1中斷服務程序 { u8 Res; if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //接收中斷(接收到的數據必須是0x0d 0x0a結尾) { Res =USART_ReceiveData(USART1); //讀取接收到的數據 } if(USART_GetITStatus(USART1, USART_IT_TXE) != RESET)//發送中斷 { if(BuffCnt--) { USART_SendData(USART1,*dat);//發送數據 dat++; } else { //發送字節結束 USART_ClearITPendingBit(USART1,USART_IT_TXE); USART_ITConfig(USART1, USART_IT_TXE, DISABLE); USART_ITConfig(USART1, USART_IT_TC, ENABLE); } } //發送完成 if (USART_GetITStatus(USART1, USART_IT_TC) != RESET) { USART_ClearITPendingBit(USART1,USART_IT_TC); USART_ITConfig(USART1, USART_IT_TC, DISABLE); } }
uint8_t aaa[1024]={1,2,3,42,0}; int main(void) { NVIC_Configuration(); Led_Gpio_Init(); Timer2_Config(); uart_init(115200); //串口初始化爲115200while(1) { UsartOutChar(aaa,10); delay_ms(10); } }
其實環形隊列就是把一個數據的收尾相接spa
加一個緩衝區---假設是下面這樣子,中斷髮送的數據從這個緩衝區裏面取指針
而後呢,接着又填入了code
接着blog
假設我又想添加數據,但是呢後面空的那一塊數據空間不夠了......要是能把數組的尾和頭聯繫起來就好啦......
假設加滿了,,,若是能自動的加到前面就好啦.....
今天先這樣...太晚啦..如今最大的願望何時能安心睡個早覺..再這樣下去真擔憂會掛了......有空再詳加..
下面是實現程序--實現程序是本身想學Esp8266鏈接機智雲的時候無心中看到的,,,,,記得 天魯哥 曾經說過環形隊列實現的很巧妙,,,改天有空再研究下當初天魯哥給的程序
往裏面加數據尾指針向右增長...加到頭回到首地址
從裏面讀數據頭指針向右增長...加到頭回到首地址
注意
仍是在嘮叨嘮叨
rb_t pRb; ///< 環形緩衝區結構體變量 uint8_t rbBuf[RB_MAX_LEN]; ///< 環形緩衝區數據緩存區 void rbCreate(rb_t* rb,u8 *Buff,uint32_t BuffLen)//建立或者說初始化環形緩衝區 { if(NULL == rb) { printf("ERROR: input rb is NULL\n"); return; } rb->rbCapacity = BuffLen; rb->rbBuff = Buff; rb->rbHead = rb->rbBuff;//頭指向數組首地址 rb->rbTail = rb->rbBuff;//尾指向數組首地址 } void rbDelete(rb_t* rb)//刪除一個環形緩衝區 { if(NULL == rb) { printf("ERROR: input rb is NULL\n"); return; } rb->rbBuff = NULL;//地址賦值爲空 rb->rbHead = NULL;//頭地址爲空 rb->rbTail = NULL;//尾地址尾空 rb->rbCapacity = 0;//長度爲空 } int32_t rbCapacity(rb_t *rb)//獲取鏈表的長度 { if(NULL == rb) { printf("ERROR: input rb is NULL\n"); return -1; } return rb->rbCapacity; } int32_t rbCanRead(rb_t *rb)//返回能讀的空間 { if(NULL == rb) { printf("ERROR: input rb is NULL\n"); return -1; } if (rb->rbHead == rb->rbTail)//頭與尾相遇 { return 0; } if (rb->rbHead < rb->rbTail)//尾大於頭 { return rb->rbTail - rb->rbHead; } return rbCapacity(rb) - (rb->rbHead - rb->rbTail);//頭大於尾 } int32_t rbCanWrite(rb_t *rb)//返回能寫入的空間 { if(NULL == rb) { printf("ERROR: input rb is NULL\n"); return -1; } return rbCapacity(rb) - rbCanRead(rb);//總的減去已經寫入的空間 } /* rb--要讀的環形鏈表 data--讀出的數據 count--讀的個數 */ int32_t rbRead(rb_t *rb, void *data, size_t count) { int copySz = 0; if(NULL == rb) { printf("ERROR: input rb is NULL\n"); return -1; } if(NULL == data) { printf("ERROR: input data is NULL\n"); return -1; } if (rb->rbHead < rb->rbTail)//尾大於頭 { copySz = min(count, rbCanRead(rb));//查看能讀的個數 memcpy(data, rb->rbHead, copySz);//讀出數據到data rb->rbHead += copySz;//頭指針加上讀取的個數 return copySz;//返回讀取的個數 } else //頭大於等於了尾 { if (count < rbCapacity(rb)-(rb->rbHead - rb->rbBuff))//讀的個數小於頭上面的數據量 { copySz = count;//讀出的個數 memcpy(data, rb->rbHead, copySz);// rb->rbHead += copySz; return copySz; } else//讀的個數大於頭上面的數據量 { copySz = rbCapacity(rb) - (rb->rbHead - rb->rbBuff);//先讀出來頭上面的數據 memcpy(data, rb->rbHead, copySz); rb->rbHead = rb->rbBuff;//頭指針指向數組的首地址 //還要讀的個數 copySz += rbRead(rb, (char*)data+copySz, count-copySz);//接着讀剩餘要讀的個數 return copySz; } } } int32_t rbWrite(rb_t *rb, const void *data, size_t count) { int tailAvailSz = 0; if(NULL == rb) { printf("ERROR: rb is empty \n"); return -1; } if(NULL == data) { printf("ERROR: data is empty \n"); return -1; } if (count >= rbCanWrite(rb))//若是剩餘的空間不夠 { printf("ERROR: no memory \n"); return -1; } if (rb->rbHead <= rb->rbTail)//頭小於等於尾 { tailAvailSz = rbCapacity(rb) - (rb->rbTail - rb->rbBuff);//查看尾上面剩餘的空間 if (count <= tailAvailSz)//個數小於等於尾上面剩餘的空間 { memcpy(rb->rbTail, data, count);//拷貝數據到環形數組 rb->rbTail += count;//尾指針加上數據個數 if (rb->rbTail == rb->rbBuff+rbCapacity(rb))//正好寫到最後 { rb->rbTail = rb->rbBuff;//尾指向數組的首地址 } return count;//返回寫入的數據個數 } else { memcpy(rb->rbTail, data, tailAvailSz);//填入尾上面剩餘的空間 rb->rbTail = rb->rbBuff;//尾指針指向數組首地址 //剩餘空間 剩餘數據的首地址 剩餘數據的個數 return tailAvailSz + rbWrite(rb, (char*)data+tailAvailSz, count-tailAvailSz);//接着寫剩餘的數據 } } else //頭大於尾 { memcpy(rb->rbTail, data, count); rb->rbTail += count; return count; } } /**@} */ /** * @brief 向環形緩衝區寫入數據 * @param [in] buf : buf地址 * @param [in] len : 字節長度 * @return 正確 : 返回寫入的數據長度 失敗 : -1 */ int32_t PutData(uint8_t *buf, uint32_t len) { int32_t count = 0; if(NULL == buf) { printf("ERROR: gizPutData buf is empty \n"); return -1; } count = rbWrite(&pRb, buf, len); if(count != len) { printf("ERROR: Failed to rbWrite \n"); return -1; } USART_ITConfig(USART1, USART_IT_TXE, ENABLE); return count; }
#ifndef LOOPLIST_H_ #define LOOPLIST_H_ #ifndef LOOPLIST_C_//若是沒有定義 AnnularArray_C_ #define LOOPLIST_C_ extern #else #define LOOPLIST_C_ #endif #include <stm32f10x.h> #define size_t uint16_t #define RB_MAX_LEN 1024 //緩衝區最大長度 #define min(a, b) (a)<(b)?(a):(b) ///< 獲取最小值 /** 環形緩衝區數據結構 */ typedef struct { size_t rbCapacity;//空間大小 uint8_t *rbHead; //頭 uint8_t *rbTail; //尾 uint8_t *rbBuff; //數組的首地址 }rb_t; LOOPLIST_C_ rb_t pRb; ///< 環形緩衝區結構體變量 LOOPLIST_C_ uint8_t rbBuf[RB_MAX_LEN]; ///< 環形緩衝區數據緩存區 LOOPLIST_C_ void rbCreate(rb_t *rb,u8 *Buff,uint32_t BuffLen);//建立或者說初始化環形緩衝區 LOOPLIST_C_ void rbDelete(rb_t* rb); LOOPLIST_C_ int32_t rbCapacity(rb_t *rb);//獲得環形大小 LOOPLIST_C_ int32_t rbCanRead(rb_t *rb);//能讀出數據的個數 LOOPLIST_C_ int32_t rbCanWrite(rb_t *rb);//還剩餘的空間 LOOPLIST_C_ int32_t rbRead(rb_t *rb, void *data, size_t count);//讀取數據 LOOPLIST_C_ int32_t rbWrite(rb_t *rb, const void *data, size_t count); LOOPLIST_C_ int32_t PutData(uint8_t *buf, uint32_t len); #endif
使用就很方便了--直接往裏面填數據就好啦
#include "include.h" uint8_t aaa[50]={1,1,1,1,1,1,1,1,1,1}; uint8_t bbb[50]={3,3,3,3,3,3,3,3,3,3}; int main(void) { NVIC_Configuration(); Led_Gpio_Init(); Timer2_Config(); uart_init(115200); //串口初始化爲115200 rbCreate(&pRb,SendBuff,USART_REC_LEN);//建立環形隊列 while(1) { PutData(aaa,10);//發送數據 PutData(bbb,10);//發送數據 delay_ms(10); } }
void USART1_IRQHandler(void) //串口1中斷服務程序 { u8 Res; if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //接收中斷(接收到的數據必須是0x0d 0x0a結尾) { Res =USART_ReceiveData(USART1); //讀取接收到的數據 } if(USART_GetITStatus(USART1, USART_IT_TXE) != RESET) { if(rbCanRead(&pRb)>0)//若是裏面的數據個數大於0 { rbRead(&pRb, &SendDat, 1);//讀取一個數據 USART_SendData(USART1, SendDat);//發送 } else { //發送字節結束 USART_ClearITPendingBit(USART1,USART_IT_TXE); USART_ITConfig(USART1, USART_IT_TXE, DISABLE); USART_ITConfig(USART1, USART_IT_TC, ENABLE); } } //發送完成 if (USART_GetITStatus(USART1, USART_IT_TC) != RESET) { USART_ClearITPendingBit(USART1,USART_IT_TC); USART_ITConfig(USART1, USART_IT_TC, DISABLE); } }
其實再完美點就是加上DMA....後期我儘可能用LPC的單片機作....不對是必定要用LPC的單片機作成dma的---
程序連接:http://pan.baidu.com/s/1pLlXDfP 密碼:6kci