C语言多线程内存管理模块
摘要:一个多线程动态内存管理模块,可以有效地检测C语言中内存泄漏和内存越界等错误。
1原理
●分配
通过重新改写内存分配函数,把调用时的信息保存在一个节点中,节点中包括此内存分配的首地址,大小以及分配所在的源文件、函数、行号,并用一个HASH表来保存所有节点。
●越界检测
为了检测写越界的错误,在用户申请的内存前后各增加了一定大小的内存作为监测区域,并初始化成预定值(0xdeadbeef)。如果发生越界写操作时,预定值就会发生改变,即可检测到越界操作错误。
●释放
重新改写内存释放函数free,释放时节点从HASH表中删除并进行越界检测。
●查看
手动调用show_memory()或show_memory_summary()查看内存使用情况并进行越界检测。
以下涉及内存分配和内存释放的函数被重新改写:
1.malloc
2.calloc
3.realloc
4.strdup
5.strndup
6.asprintf
7.vasprintf
HASH表如下图所示:
节点结构如下:
static struct mm_region
{
struct mm_region *next;
char file[40]; /* 分配所在的文件 */
char func[40]; /* 分配所在的函数 */
unsigned int lineno; /* 分配所在的行 */
size_t len; /* 内存分配的大小 */
unsigned int fence; /* 内存起始边界,用于头越界检测 */
unsigned char data[0]; /* 用户内存分配首地址,malloc等函数返回以此为首地址的len长度的一块内存 */
} *regions[SOME_PRIME];
内存中一条节点的结构:
2测试
步骤:
1.引入头文件:在需要检测的C/C++文件中引入”mm.h”头文件;
2.查看内存使用情况:调用show_memory()函数查看本文件中内存泄漏详细情况,或调用
show_memory_summary()函数查看本文件中内存泄漏统计情况。
2.1内存泄漏
2.1.1测试代码
#include
/* 加入头文件mm.h */
#include"mm.h"
int main(int argc, char *argv[]) {
char *mp = NULL;
char *cp = NULL;
mp = (char *)malloc(6);
cp = (char *)calloc(1,10);
/* 查看内存泄漏 */
show_memory();
show_memory_summary();
return 0;
}
2.1.2测试结果
2.2内存越界
2.2.1测试代码
#include
/* 加入头文件mm.h */
#include"mm.h"
int main(int argc, char *argv[]) {
char *mp = NULL;
mp = (char *)malloc(6);
/* 越界操作 */
memset(mp,0, 10);
/* 释放或查看内存时检测 */
free(mp);
return 0;
}
2.2.2测试结果
2.3释放错误
此类错误包括:
1.释放空指针
2.释放野指针
3.重复释放
4.内存释放的起始地址与内存分配的起始地址不一致2.3.1测试代码
#include
/* 加入头文件mm.h */
#include"mm.h"
int main(int argc, char *argv[])
{
char *mp = NULL;
mp = (char *)malloc(6);
free(mp);
/* 重复释放*/
free(mp);
return 0;
}
2.3.2测试结果
3源码
两个文件:”mm.h”和“mm.c”
3.1mm.h
/*
* mm.h
*
* memory usage debugging (from Asterisk)
*/
#ifndef __MM_H__
#define __MM_H__
#ifdef __cplusplus
extern "C" {
#endif
/* Undefine any macros */
#undef malloc
#undef calloc
#undef free
#undef realloc
#undef strdup
#undef strndup
#undef asprintf
#undef vasprintf
void *__mm_calloc(size_t nmemb, size_t size, const char *file, int lineno, const char *func);
void *__mm_malloc(size_t size, const char *file, int lineno, const char *func); void __mm_free(void *ptr, const char *file, int lineno, const char *func);
void *__mm_realloc(void *ptr, size_t size, const char *file, int lineno, const char *func);
char *__mm_strdup(const char *s, const char *file, int lineno, const char *func); char *__mm_strndup(const char *s, size_t n, const char *file, int lineno, const char
*func);
int __mm_asprintf(const char *file, int lineno, const char *func, char **strp, const char *format, ...);
int __mm_vasprintf(char **strp, const char *format, va_list ap, const char *file, int lineno, const char *func);
/* Provide our own definitions */
#define calloc(a,b) \
__mm_calloc(a,b,__FILE__, __LINE__, __PRETTY_FUNCTION__)
#define malloc(a) \
__mm_malloc(a,__FILE__, __LINE__, __PRETTY_FUNCTION__)
#define free(a) \
__mm_free(a,__FILE__, __LINE__, __PRETTY_FUNCTION__)
#define realloc(a,b) \
__mm_realloc(a,b,__FILE__, __LINE__, __PRETTY_FUNCTION__)
#define strdup(a) \
__mm_strdup(a,__FILE__, __LINE__, __PRETTY_FUNCTION__)
#define strndup(a,b) \
__mm_strndup(a,b,__FILE__, __LINE__, __PRETTY_FUNCTION__)
#define asprintf(a, b, c...) \
__mm_asprintf(__FILE__, __LINE__, __PRETTY_FUNCTION__, a, b, c)
#define vasprintf(a,b,c) \
__mm_vasprintf(a,b,c,__FILE__, __LINE__, __PRETTY_FUNCTION__)
int s how_memory(void);
int s how_memory_summary(void);
#ifdef __cplusplus
}
#endif
#endif/* __MM_H__ */
3.2mm.c
/*
* mm.c
*
* Memory Management (from Asterisk)
*
*/
#include
#include
#include
#include
#include
#include"mm.h"
/* 本文中不使用自定义malloc,calloc,free等函数*/
#undef malloc
#undef calloc
#undef realloc
#undef strdup
#undef strndup
#undef free
#undef vasprintf
#undef asprintf
#define SOME_PRIME 563
#define FENCE_MAGIC 0xdeadbeef
static struct mm_region
{
struct mm_region *next;
char file[40]; /* 分配所在的文件*/
char func[40]; /* 分配所在的函数*/
unsigned int lineno; /* 分配所在的行*/
size_t len; /* 内存分配的大小*/
unsigned int fence; /* 内存起始边界,用于头越界检测*/
unsigned char data[0]; /* 用户内存分配首地址,malloc等函数返回以此为首地址的len长度的一块内存*/
} *regions[SOME_PRIME];
#define HASH(a) \
(((unsigned long)(a)) % SOME_PRIME)
static pthread_mutex_t mmlock = PTHREAD_MUTEX_INITIALIZER;
#define mm_log(...) \
do { \
fprintf(stderr, __VA_ARGS__); \
} while (0)
static inline void*__mm_alloc_region(size_t size, const char*file, int lineno, const char *func)
{
struct mm_region *reg;
void *ptr = NULL;
unsigned int *fence;
int hash;
if (!(reg = (struct mm_region *)malloc(size + sizeof(*reg) +
sizeof(*fence) ))) /* 使用系统malloc */
{
mm_log("Memory Allocation Failure - '%d' bytes in function %s "
"at line %d of %s\n", (int) size, func, lineno, file);
}
strncpy(reg->file, file, sizeof(reg->file));
strncpy(reg->func, func, sizeof(reg->func));
reg->lineno = lineno;
reg->len = size;
ptr = reg->data;
hash = HASH(ptr);
/* 内存起始标志*/
reg->fence = FENCE_MAGIC;
/* 内存结束标志*/
fence = (unsigned int *)(ptr + reg->len);
*fence =FENCE_MAGIC;
pthread_mutex_lock(&mmlock);
reg->next = regions[hash]; /* 一个hash可能对应多个值*/
regions[hash] = reg;
pthread_mutex_unlock(&mmlock);
return ptr;
}
static inline size_t __mm_sizeof_region(void *ptr)
{
int hash = HASH(ptr);
struct mm_region *reg;
size_t len = 0;
pthread_mutex_lock(&mmlock);
for (reg = regions[hash]; reg; reg = reg->next)
{
if (reg->data == ptr)
{
len = reg->len;
break;
}
}
pthread_mutex_unlock(&mmlock);
return len;
}
static void__mm_free_region(void*ptr, const char*file, int lineno, const char *func)
{
int hash = HASH(ptr);
struct mm_region *reg, *prev = NULL;
unsigned int *fence;
pthread_mutex_lock(&mmlock);
for (reg = regions[hash]; reg; reg = reg->next)
{
if (reg->data == ptr)
{
if (prev)
prev->next = reg->next;
else
regions[hash] = reg->next;
break;
}
prev = reg;
}
pthread_mutex_unlock(&mmlock);
if (reg)
{
/* 头越界检测*/
if (reg->fence != FENCE_MAGIC)
{
mm_log("WARNING: Head fence violation at %p, in %s of %s, "
"line %d\n", reg->data, reg->func, reg->file, reg->lineno);
}
/* 尾越界检测*/
fence = (unsigned int *)(reg->data + reg->len);
if ( *fence != FENCE_MAGIC)
{
mm_log("WARNING: Tail fence violation at %p, in %s of %s, "
"line %d\n", reg->data, reg->func, reg->file, reg->lineno);
}
free(reg);
} else
{
mm_log("WARNING: Freeing unused memory at %p, in %s of %s, line %d\n",
ptr, func, file, lineno);
}
}
void*__mm_calloc(size_t nmemb, size_t size, const char*file, int lineno, const char *func)
{
void *ptr;
if ((ptr = __mm_alloc_region(size * nmemb, file, lineno, func))) memset(ptr, 0, size * nmemb);
return ptr;
}
void *__mm_malloc(size_t size, const char *file, int lineno, const char *func) {
return __mm_alloc_region(size, file, lineno, func);
}
void __mm_free(void *ptr, const char *file, int lineno, const char *func) {
__mm_free_region(ptr, file, lineno, func);
void *__mm_realloc(void *ptr, size_t size, const char *file, int lineno, const char *func)
{
void *tmp;
size_t len = 0;
if (ptr && !(len = __mm_sizeof_region(ptr))) {
mm_log("WARNING: Realloc of unalloced memory at %p, in %s of %s, "
"line %d\n", ptr, func, file, lineno);
return NULL;
}
if (!(tmp = __mm_alloc_region(size, file, lineno, func)))
return NULL;
if (len > size)
len = size;
if (ptr) {
memcpy(tmp, ptr, len);
__mm_free_region(ptr, file, lineno, func);
}
return tmp;
}
char*__mm_strdup(const char*s, const char*file, int lineno, const char*func) {
size_t len;
void *ptr;
if (!s)
return NULL;
len = strlen(s) + 1;
if ((ptr = __mm_alloc_region(len, file, lineno, func)))
strcpy((char *)ptr, s);
return (char *)ptr;
}
char*__mm_strndup(const char*s, size_t n, const char*file, int lineno, const char *func)
size_t len;
void *ptr;
if (!s)
return NULL;
len = strlen(s) + 1;
if (len > n)
len = n;
if ((ptr = __mm_alloc_region(len, file, lineno, func)))
strcpy((char *)ptr, s);
return (char *)ptr;
}
int __mm_asprintf(const char *file, int lineno, const char *func, char **strp, const char *fmt, ...)
{
int size;
va_list ap, ap2;
char s;
*strp = NULL;
va_start(ap, fmt);
va_copy(ap2, ap);
size = vsnprintf(&s, 1, fmt, ap2);
va_end(ap2);
if (!(*strp = (char *)__mm_alloc_region(size + 1, file, lineno, func))) {
va_end(ap);
return -1;
}
vsnprintf(*strp, size + 1, fmt, ap);
va_end(ap);
return size;
}
int __mm_vasprintf(char **strp, const char *fmt, va_list ap, const char *file, int lineno, const char *func)
{
int size;
va_list ap2;
char s;
*strp = NULL;
va_copy(ap2, ap);
size = vsnprintf(&s, 1, fmt, ap2);
va_end(ap2);
if (!(*strp = (char *)__mm_alloc_region(size + 1, file, lineno, func))) {
va_end(ap);
return -1;
}
vsnprintf(*strp, size + 1, fmt, ap);
return size;
}
int show_memory(void)
{
char *fn = NULL;
struct mm_region *reg;
unsigned int x;
unsigned int len = 0;
unsigned int count = 0;
unsigned int *fence;
mm_log("\nLEAK DETAIL:\n");
pthread_mutex_lock(&mmlock);
for (x = 0; x < SOME_PRIME; x++)
{
for (reg = regions[x]; reg; reg = reg->next)
{
if (!fn || !strcasecmp(fn, reg->file) || !strcasecmp(fn, "anomolies"))
{
/* 头越界检测*/
if (reg->fence != FENCE_MAGIC)
{
mm_log("WARNING: Head fence violation at %p, "
"in %s of %s, line %d\n", reg->data,
reg->func, reg->file, reg->lineno);
}
/* 尾越界检测*/
fence = (unsigned int *)(reg->data + reg->len);
if ( *fence != FENCE_MAGIC)
{
mm_log("WARNING: Tail fence violation at %p, in %s of %s, "
"line %d\n", reg->data, reg->func, reg->file,
reg->lineno);
}
}
if (!fn || !strcasecmp(fn, reg->file))
{
mm_log("%10d bytes allocated in %20s at line %5d of %s\n",
(int) reg->len, reg->func, reg->lineno, reg->file);
len += reg->len;
count++;
}
}
}
pthread_mutex_unlock(&mmlock);
mm_log("%d bytes allocated in %d allocations\n", len, count);
return 0;
}
int show_memory_summary(void)
{
char *fn = NULL;
int x;
struct mm_region *reg;
unsigned int len = 0;
int count = 0;
struct file_summary
{
char fn[80];
int len;
int count;
struct file_summary *next;
} *list = NULL, *cur;
mm_log("\nLEAK SUMMARY:\n");
pthread_mutex_lock(&mmlock);
for (x = 0; x < SOME_PRIME; x++)
{
for (reg = regions[x]; reg; reg = reg->next)
{
if (fn && strcasecmp(fn, reg->file))
continue;
for (cur = list; cur; cur = cur->next)
{
if ((!fn && !strcmp(cur->fn, reg->file)) || (fn
&& !strcmp(cur->fn, reg->func)))
break;
}
if (!cur)
{
cur = (struct file_summary *)alloca(sizeof(*cur));
memset(cur, 0, sizeof(*cur));
strncpy(cur->fn, fn ? reg->func : reg->file, sizeof(cur->fn));
cur->next = list;
list = cur;
}
cur->len += reg->len;
cur->count++;
}
}
pthread_mutex_unlock(&mmlock);
/* Dump the whole list */
for (cur = list; cur; cur = cur->next)
{
len += cur->len;
count += cur->count;
if (fn)
{
mm_log("%10d bytes in %d allocations in function '%s' of '%s'\n", cur->len, cur->count, cur->fn, fn);
} else
{
mm_log("%10d bytes in %d allocations in file '%s'\n",
cur->len, cur->count, cur->fn);
}
}
mm_log("%d bytes allocated in %d allocations\n", len, count);
return 0;
}
该程序全部由C写成没有C++ 更没用MFC 完全是自娱自乐给需要的人一个参考 #include "stdafx.h" #include
TCHAR cRecs[200],cSends[100]; //接收字符串发送字符串 char j=0,*cCom; //接收用统计数据大小变量端口选择 BOOL WINAPI Main_Proc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch(uMsg) { HANDLE_MSG(hWnd, WM_INITDIALOG, Main_OnInitDialog); HANDLE_MSG(hWnd, WM_COMMAND, Main_OnCommand); HANDLE_MSG(hWnd,WM_CLOSE, Main_OnClose); } return FALSE; } /*系统初始化函数*/ BOOL Main_OnInitDialog(HWND hwnd, HWND hwndFocus, LPARAM lParam) { HWND hwndCombo1=GetDlgItem(hwnd,IDC_COMBO1); ComboBox_InsertString(hwndCombo1,-1,TEXT("COM1")); ComboBox_InsertString(hwndCombo1,-1,TEXT("COM2"));
一个c语言的串口通信程序范例 分类:技术笔记 标签: c语言 串口通信 通信程序 it 最近接触一个项目,用HL-C1C激光位移传感器+易控组态软件完成生产线高度跳变检测,好久没有接触c c#,一些资料,找来做个记录,也许大家用的着 #include
static void interrupt far AsyncInt(void); void Init_COM(int ComPortAddr, unsigned char IntVectNum, int Baud, unsigned char Data, unsigned char Stop, unsigned char Parity) { unsigned char High,Low; int f; comportaddr=ComPortAddr; intvectnum=IntVectNum; CharsInBuf=0;CircIn=0;CircOut=0; f=(Baud/100); f=1152/f; High=f/256; Low=f-High*256; outp(ComPortAddr+3,0x80); outp(ComPortAddr,Low); outp(ComPortAddr+1,High); Data=(Data-5)|((Stop-1)*4); if(Parity==2) Data=Data|0x18; else if(Parity==1) Data=Data|0x8; outp(ComPortAddr+3,Data); outp(ComPortAddr+4,0x0a);
一、程序代码 #include
TI = 0; } T_counter = 0; } uart_receive(void) interrupt 4 { if(RI) { RI = 0; indata[R_counter] = SBUF; R_counter++; if(R_counter>=4) { R_counter = 0; flag = 1; } } } void system_initial(void) { P1M1 = 0x00; P1M0 = 0xff; P1 = 0xff; //初始化为全部关闭 temp3 = 0x3f;//初始化temp3的值与六路输出的初始值保持一致 temp = 0xf0; R_counter = 0; T_counter = 0; } void initial_comm(void) { SCON = 0x50; //设定串行口工作方式:mode 1 ; 8-bit UART,enable ucvr TMOD = 0x21; //TIMER 1;mode 2 ;8-Bit Reload PCON = 0x80; //波特率不加倍SMOD = 1 TH1 = 0xfa; //baud: 9600;fosc = 11.0596 IE = 0x90; // enable serial interrupt TR1 = 1; // timer 1 RI = 0; TI = 0; ES = 1; EA = 1; }
c语言串口通信范例 This manuscript was revised by the office on December 22, 2012
一个c语言的串口通信程序范例 标签:分类: 最近接触一个项目,用HL-C1C激光位移传感器+易控组态软件完成生产线高度跳变检测,好久没有接触c c#,一些资料,找来做个记录,也许大家用的着 #include <> #include <> #include <> #include <> #define COM232 0x2f8 #define COMINT 0x0b #define MaxBufLen 500 #define Port8259 0x20 #define EofInt 0x20
static int comportaddr; static char intvectnum; static unsigned char maskb; static unsigned char Buffer[MaxBufLen]; static int CharsInBuf,CircIn,CircOut; static void (interrupt far *OldAsyncInt)(); static void interrupt far AsyncInt(void); void Init_COM(int ComPortAddr, unsigned char IntVectNum, int Baud, unsigned char Data, unsigned char Stop, unsigned char Parity) { unsigned char High,Low; int f; comportaddr=ComPortAddr; intvectnum=IntVectNum; CharsInBuf=0;CircIn=0;CircOut=0; f=(Baud/100);
#include
void main() { delayms(100); init(); //初始化系统 delayms(100); init_wdt(); //初始化看门狗 while(1) { while(!RI_0) //是否收到数据 { clr_wdt(); } RI_0=0; //清除接收中断标志 buffer=S0BUF; if(buffer==0x5a) //检测祯头0 start0=1; if(buffer==0x54) //检测祯头1 start1=1; if(buffer==0x5a) //检测祯尾0 end0=1; if(buffer==0xfe) //检测祯尾1 end1=1; if((start0==1)&(start1==1)) { buff[i]=buffer; //从祯头1开始存储数据 i++; } if((end0==1)&(end1==1)) //是否已经接收祯尾 { count=i; //数据长度为count个 i=1; if((buff[2]==0x03)&(count==107)) //是否422指令 { buff[0]=0x5a; //重填祯头0 buff[count-4]=0; //校验和清零 for(k=2;k<(count-4);k++) //计算校验和 { buff[count-4]+=buff[k]; } for(k=0;k S0BUF=buff[k]; while(!TI_0); //等待发送完成 TI_0=0; //清除发送中断标志 } reset(); } else if((buff[2]==0x05)&(count==7)) //是否AD测试指令 { sendad(); reset(); } else if((buff[2]==0x18)&(count==7)) //是否发送时序信号指令 { sendpaulse(); reset(); } else //如果接收错误,则恢复各标志位为初始状态以便下次接收 { reset(); } } } } void reset() { start0=0; //祯头祯尾标志位清零 start1=0; end0=0; end1=0; for(k=0;k c语言串口通信范例标准化管理处编码[BBX968T-XBB8968-NNJ668-MM9N] 一个c语言的串口通信程序范例 标签:分类: 最近接触一个项目,用HL-C1C激光位移传感器+易控组态软件完成生产线高度跳变检测,好久没有接触c c#,一些资料,找来做个记录,也许大家用的着 #include <> #include <> #include <> #include <> #define COM232 0x2f8 #define COMINT 0x0b #define MaxBufLen 500 #define Port8259 0x20 #define EofInt 0x20 static int comportaddr; static char intvectnum; static unsigned char maskb; static unsigned char Buffer[MaxBufLen]; static int CharsInBuf,CircIn,CircOut; static void (interrupt far *OldAsyncInt)(); static void interrupt far AsyncInt(void); void Init_COM(int ComPortAddr, unsigned char IntVectNum, int Baud, unsigned char Data, unsigned char Stop, unsigned char Parity) { unsigned char High,Low; int f; comportaddr=ComPortAddr; intvectnum=IntVectNum; CharsInBuf=0;CircIn=0;CircOut=0; ? /*write*/ #include 摘要: 本文说明了异步串行通信(RS-232)的工作方式,探讨了查询和中断两种软件接口利弊,并给出两种方式的C语言源程序的I/O通道之一,以最简单方式组成的串行双工线路只需两条信号线和一条公共地线,因此串行通信既有线路简单的优点同时也有它的缺点,即通信速率无法同并行通信相比,实际上EIA RS-232C在标准条件下的最大通信速率仅为20Kb/S。 尽管如此,大多数外设都提供了串行口接口,尤其在工业现场 RS-232C的应用更为常见。IBM PC及兼容机系列都有RS-232的适配器,操作系统也提供了编程接口,系统接口分为DOS功能调用和BIOS 功能调用两种:DOS INT 21H的03h和04h号功能调用为异步串行通信的接收和发送功能;而BIOS INT 14H有4组功能调用为串行通信服务,但DOS和BIOS功能调用都需握手信号,需数根信号线连接或彼此间互相短接,最为不便的是两者均为查询方式,不提供中断功能,难以实现高效率的通信程序,为此本文采用直接访问串行口硬件端口地址的方式,用C语言编写了串行通信查询和中断两种方式的接口程序。 1.串行口工作原理 微机串行通信采用EIA RS-232C标准,为单向不平衡传输方式,信号电平标准±12V,负逻辑,即逻辑1(MARKING)表示为信号电平-12V,逻辑0(SPACING)表示为信号电平12V,最大传送距离15米,最大传送速率19.6K波特,其传送序列如图1,平时线路保持为1,传送数据开始时,先送起始位(0),然后传8(或7,6,5)个数据位(0,1), 接着可传1位奇偶校验位,最后为1~2个停止位(1),由此可见,传送一个ASCII字符(7位),加上同步信号最少需9位数据位。 @@T8S12300.GIF;图1@@ 串行通信的工作相当复杂,一般采用专用芯片来协调处理串行数据的发送接收,称为通用异步发送/接收器(UART),以节省CPU的时间,提高程序运行效率,IBM PC系列采用8250 UART来处理串行通信。在BIOS数据区中的头8个字节为4个UART的端口首地址,但DOS 只支持2个串行口:COM1(基地址0040:0000H)和COM2(基地址0040:0002H)。8250 UART共有10个可编程的单字节寄存器,占用7个端口地址,复用地址通过读/写操作和线路控制寄存器的第7位来区分。这10个寄存器的具体功能如下: COM1(COM2) 寄存器 端口地址功能DLAB状态 3F8H(2F8H) 发送寄存器(写) 0 3F8H(2F8H) 接收寄存器(读) 0 3F8H(2F8H) 波特率因子低字节1 3F9H(2F9H) 波特率因子高字节1 3F9H(2F9H) 中断允许寄存器0 3FAH(2FAH) 中断标志寄存器 3FBH(2FBH) 线路控制寄存器 3FCH(2FCH) MODEM控制寄存器 3FDH(2FDH) 线路状态寄存器 c语言串口通信范例 SANY GROUP system office room 【SANYUA16H- 一个c语言的串口通信程序范例 分类:技术笔记 标签: c语言 串口通信 通信程序 it 最近接触一个项目,用HL-C1C激光位移传感器+易控组态软件完成生产线高度跳变检测,好久没有接触c c#,一些资料,找来做个记录,也许大家用的着 #include static void interrupt far AsyncInt(void); void Init_COM(int ComPortAddr, unsigned char IntVectNum, int Baud, unsigned char Data, unsigned char Stop, unsigned char Parity) { unsigned char High,Low; int f; comportaddr=ComPortAddr; intvectnum=IntVectNum; CharsInBuf=0;CircIn=0;CircOut=0; f=(Baud/100); f=1152/f; High=f/256; Low=f-High*256; outp(ComPortAddr+3,0x80); outp(ComPortAddr,Low); outp(ComPortAddr+1,High); Data=(Data-5)|((Stop-1)*4); if(Parity==2) Data=Data|0x18; else if(Parity==1) Data=Data|0x8; outp(ComPortAddr+3,Data); outp(ComPortAddr+4,0x0a); #include 用C语言实现串口通信 姓名: 学号: 专业:通信工程 用C语言实现串口通信(单片机和单片机) 摘要:介绍用汇编语言实现单片机与单片机之间的串口通信,通过对其中一个单片机的操作,完成另一个单片机功能的实现。并介绍了实现该功能的原理算法、硬件框图、软件流程图,以及调试过程、步骤和结果。并对结果进行了分析。 引言:简要介绍了RS232,为什么要用RS232 ,RS232和其他接口的比较优缺点。 原理: 1什么是RS232:RS是指推荐标准的英文缩写,232是标识号。RS232是由电子工业协会(Electronic Industries Association,EIA) 所制定的异步传输标准接口,是个人计算机上的通讯接口之一。通常RS-232 接口以9个引脚(DB-9) 或是25个引脚(DB-25) 的型态出现,一般个人计算机上会有两组RS-232 接口,分别称为COM1 和COM2。 2.RS232接口及其接法 实现RS232通信的关键点是:RXD连TXD,TXD连RXD,GND接地。只要这三根线连接好,就可以实现串口通信。 3.串口初始化 串行口工作之前,应对其进行初始化,主要是设置产生波特率的定时器1、串行口控制和中断控制。具体步骤如下: ●确定T1的工作方式(编程TMOD寄存器); ●计算T1的初值,装载TH1、TL1; ●启动T1(编程TCON中的TR1位); ●确定串行口控制(编程SCON寄存器);串行口在中断方式工作时,要进行中断设置(编 程IE、IP寄存器)。 4.语句说明 1)发送函数 void com(uchar com) { SBUF=com; while(!TI); TI=0; } 2)串口初始化 一、引言: 现在在工业现场很少有人再用C语言做串口通讯程序了,但是基于DOS环境的程序还是有它的优势的。DOS系统的单任务环境是系统运行更加稳定、可靠;在一些追求很高的可靠性的系统中还是有一定的价值的。本文通过C语言控制PLC实现简单的物料传送为例子。 二、硬件介绍: 1、CPM1A采用RS232串口通讯与上位机连接,在PLC的DM区中可以设定串口参数,本文采用默认值: 串口通信格式: 1位---起始位、9600---波特率、7位---数据位、2位---停止位、偶校验 2、C语言中用于串口读写的函数:bioscom,在bios.h头文件中。 Bioscom用法:bioscom(int cmd,char byte,int port) Cmd的值:0 设置通信参数为btye值 1 发送一个字符到串口 2 从串口接收一个字符 3 返回串口端口的状态 byte的值:0x02 7数据位0x03 8位数据位 0x00 1个停止位0x04 2个停止位 0x00 无奇偶校验0x08奇校验 0x18偶校验0x80 1200波特率 0xA0 2400波特率0xC0 4800波特率 0xE0 9600波特率 注意:在对串口初始化时,上述参数值相或附给byte。 Port的值:0 端口1 1 端口2 三、完整源代码: #include /* 此头函数请不要删除*/ #include #include #define F1 0x3B /*启动*/ #define F2 0x3C /*停止*/ #define F3 0x3D /*混料*/ #define F4 0x3E /*出料*/ #define F5 0x3F /*退出*/ #define PORT 0 /*定义端口号*/ #define SETTINGS (0x02|0x04|0x18|0xE0) /*设定参数*/ /* 定义发送字符函数send */ void sendPort(int port,char cc) { union{ char ch[2]; int status; 一个c语言的串口通信程序例 标签: 分类:技术笔记 c语言 串口通信 通信程序 it 最近接触一个项目,用HL-C1C激光位移传感器+易控组态软件完成生产线高度跳变检测,好久没有接触c c#,一些资料,找来做个记录,也许大家用的着 #include 一个c语言的串口通信程序范例 标签: 分类:技术笔记 c语言 串口通信 通信程序 it 最近接触一个项目,用HL-C1C激光位移传感器+易控组态软件完成生产线高度跳变检测,好久没有接触c c#,一些资料,找来做个记录,也许大家用的着 #include 摘要本文说明了异步串行通信(RS-232)的工作方式,探讨了查询和中断两种软件接口利弊,并给出两种方式的C语言源程序。 的I/O通道之一,以最简单方式组成的串行双工线路只需两条信号线和一条公共地线,因此串行通信既有线路简单的优点同时也有它的缺点,即通信速率无法同并行通信相比,实际上EIA RS-232C在标准条件下的最大通信速率仅为20Kb/S。尽管如此,大多数外设都提供了串行口接口,尤其在工业现场RS-232C的应用更为常见。IBM PC及兼容机系列都有RS-232的适配器,操作系统也提供了编程接口,系统接口分为DOS功能调用和BIOS功能调用两种:DOS INT 21H的03h和04h号功能调用为异步串行通信的接收和发送功能;而BIOS INT 14H有4组功能调用为串行通信服务,但DOS和BIOS功能调用都需握手信号,需数根信号线连接或彼此间互相短接,最为不便的是两者均为查询方式,不提供中断功能,难以实现高效率的通信程序,为此本文采用直接访问串行口硬件端口地址的方式,用C语言编写了串行通信查询和中断两种方式的接口程序。 1.串行口工作原理 微机串行通信采用EIA RS-232C标准,为单向不平衡传输方式,信号电平标准±12V,负逻辑,即逻辑1(MARKING)表示为信号电平-12V,逻辑0(SPACING)表示为信号电平+12V,最大传送距离15米,最大传送速率19.6K波特,其传送序列如图1,平时线路保持为1,传送数据开始时,先送起始位(0),然后传8(或7,6,5)个数据位(0,1),接着可传1位奇偶校验位,最后为1~2个停止位(1),由此可见,传送一个ASCII字符(7位),加上同步信号最少需9位数据位。 @@T8S12300.GIF;图1@@ 串行通信的工作相当复杂,一般采用专用芯片来协调处理串行数据的发送接收,称为通用异步发送/接收器(UART),以节省CPU的时间,提高程序运行效率,IBM PC系列采用8250 UART来处理串行通信。 在BIOS数据区中的头8个字节为4个UART的端口首地址,但DOS只支持2个串行口:COM1(基地址0040:0000H)和COM2(基地址0040:0002H)。8250 UART共有10个可编程的单字节寄存器,占用7个端口地址,复用地址通过读/写操作和线路控制寄存器的第7位来区分。这10个寄存器的具体功能如下:COM1(COM2) 寄存器 端口地址功能DLAB状态 3F8H(2F8H) 发送寄存器(写) 0 3F8H(2F8H) 接收寄存器(读) 0 3F8H(2F8H) 波特率因子低字节1 3F9H(2F9H) 波特率因子高字节1 3F9H(2F9H) 中断允许寄存器0 3FAH(2FAH) 中断标志寄存器 3FBH(2FBH) 线路控制寄存器 3FCH(2FCH) MODEM控制寄存器 3FDH(2FDH) 线路状态寄存器 3FEH(2FEH) MODEM状态寄存器 注:DLAB为线路控制寄存器第七位在编写串行通信程序时,若采用低级方式,只需访问UART的这10个寄存器即可,相对于直接控制通信的各个参量是方便 该程序全部由C写成没有C++更没用MFC 完全是自娱自乐给需要的人一个参考 #include "stdafx.h" #include return FALSE; } /* 系统初始化函数*/ BOOL Main_OnInitDialog(HWND hwnd, HWND hwndFocus, LPARAMlParam) { HWND hwndCombo1=GetDlgItem(hwnd,IDC_COMBO1); ComboBox_InsertString(hwndCombo1,-1,TEXT("COM1")); ComboBox_InsertString(hwndCombo1,-1,TEXT("COM2")); ComboBox_InsertString(hwndCombo1,-1,TEXT("COM3")); ComboBox_InsertString(hwndCombo1,-1,TEXT("COM4")); ComboBox_InsertString(hwndCombo1,-1,TEXT("COM5")); ComboBox_SetCurSel(hwndCombo1,0); void CALLBACK TimerProc (HWND hwnd, UINT message, UINT iTimerID,DWORD dwTime); SetTimer(hwnd,1,1000,TimerProc); return TRUE; } /* 监视串口错误时使用的函数*/ boolProcessErrorMessage(char* ErrorText) char *Temp = new char[200]; LPVOID lpMsgBuf; FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER |c语言串口通信范例
串口通信linux c语言实现
C语言实现串口通信
c语言串口通信范例
51单片机的串口通信程序(C语言)
用C语言实现串口通信
C语言 做串口通讯程序
c语言串口通信范例
c语言串口通信范例
C语言实现串行通信接口程序
C语言串口通信助手代码