STM32 实验

GPIO八种模式:

1、输入浮空:信号输入后没有上下拉电阻,经过施密特触发器转换为0,1信号->进入输入寄存器
2、输入上拉:信号输入后有上拉电阻 经过施密特触发器转换为0,1信号->进入输入寄存器
3、输入下拉:信号输入后有下拉电阻 经过施密特触发器转换为0,1信号->进入输入寄存器
4、模拟输入:信号输入 不经过施密特
5、开漏输出:CPU写入位设置寄存器->输出寄存器(ODR)->输出控制电路->如果是1,低电平Nmos管截止,外部上拉下拉决定。如果是0,低电平Nmos管开启,电平被拉低到0
6、推挽输出:CPU写入位设置寄存器->输出寄存器(ODR)->输出控制电路->如果是1,低电平Nmos管截止,高电平P-Mos导通;如果是0,低电平Nmos管导通,高电平P-Mos截止
7、推挽式复用功能:由外设代替CPU执行的推外输出
8、开漏复用功能:由外设功能块替代CPU决定控制电路,执行的开漏输出

STM32 实验_第1张图片


在这里插入图片描述

STM32 实验_第2张图片
STM32 实验_第3张图片
STM32 实验_第4张图片
ODR寄存器可以配置输入的上拉/下拉

STM32 实验_第5张图片
STM32 实验_第6张图片

STM32 实验_第7张图片

STM32 实验_第8张图片

STM32 实验_第9张图片

SPI 主要特点有:可以同时发出和接收串行数据;可以当作主机或从机工作;提供频率可
编程时钟;发送结束中断标志;写冲突保护;总线竞争保护等。
SPI 总线四种工作方式 SPI 模块为了和外设进行数据交换,根据外设工作要求,其输出串
行同步时钟极性和相位可以进行配置,时钟极性(CPOL)对传输协议没有重大的影响。如果
CPOL=0,串行同步时钟的空闲状态为低电平;如果 CPOL=1,串行同步时钟的空闲状态为高电
平。时钟相位(CPHA)能够配置用于选择两种不同的传输协议之一进行数据传输。如果
CPHA=0,在串行同步时钟的第一个跳变沿(上升或下降)数据被采样;如果 CPHA=1,在串
行同步时钟的第二个跳变沿(上升或下降)数据被采样。SPI 主模块和与之通信的外设备时钟
相位和极性应该一致。

STM32 实验_第10张图片

点灯

#include "Led.h"
#include "stm32f10x.h"

void LedInit(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE); //GPIOB 使能IO口时钟
	
	//GPIOE 查看入口参数 assert_param(IS_RCC_APB2_PERIPH(RCC_APB2Periph)); 之IS_RCC_APB2_PERIPH
	
	//GPIOE初始化
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE,ENABLE);
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	
	GPIO_Init(GPIOE,&GPIO_InitStructure); //初始化GPIO_Init()

	GPIO_SetBits(GPIOE, GPIO_Pin_5); //输出端口GPIOE, 高电平GPIO_Pin_5
	
	//GPIOB初始化
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	
	GPIO_Init(GPIOB,&GPIO_InitStructure); //初始化GPIO_Init()
	
	GPIO_SetBits(GPIOB, GPIO_Pin_5); //输出端口GPIOB, 高电平GPIO_Pin_5
}

#include "stm32f10x.h"
#include "Led.h"
#include "delay.h"

int main(void)
{
	delay_init();
	LedInit();
	while(1)
	{
		GPIO_SetBits(GPIOE, GPIO_Pin_5); 
		GPIO_SetBits(GPIOB, GPIO_Pin_5);
		
		delay_ms(500);
		
		GPIO_ResetBits(GPIOE, GPIO_Pin_5); 
		GPIO_ResetBits(GPIOB, GPIO_Pin_5);
		delay_ms(500);
	}
}



指针结构体复习

// CPlusDemon.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include 
void f1(int i)
{
    i = i + 1;
}

void f2(int* i)
{
    *i = *i + 1;
}

struct Employee
{
    int age;
    int height;
    int id;
    int salary;
    char name[20];
};

//typedef struct 
//{
//    int age = 11;
//    int height = 10;
//    int id = 1;
//    int salary = 2;
//    char name[20] = "zg";
//} Employee;

int main()
{
    int num = 999;
    int i = 888;
    int* p1, * p2;
    p1 = # 
    p2 = p1; //没有经过p1,直接把num的地址给了p2

    printf("%p,%p,%p\n", &num, p1, p2);

    p1 = &i; 
    printf("%p,%p,%p,%p\n", &num,&i, p1, p2); //&i, p1指向同一个, p2依然指向num
    //std::cout << "%p,%p,%p,%p\n";

    int* p = &i; //*出现在定义变量前面,表示变量是指针类型。 当*单独和变量放一起,表示读/写指向内存中的数据
    printf("%d\n" ,*p); //888

    f1(i);
    printf("%d\n", i);
    f2(&i); //指针当参数,会改变外部变量的值,ref out
    printf("%d\n", i);


    //struct Employee e1;
    //e1.age = 15;
    //strcpy_s(e1.name, "zg");
    //e1.height = 180;
    //e1.id = 2;
    //e1.salary = 99999;
    struct Employee e1 = { 18,180,1,99999,"zg" };
    struct Employee *pe1 = &e1;

    //(Employee*) # //强制转换为指针 指向

    //printf("姓名%s,年龄%d,工资%d", e1.name, e1.age, e1.salary);
    //printf("姓名%s,年龄%d,工资%d", (*pe1).name, (*pe1).age, (*pe1).salary);

    printf("姓名%s,年龄%d,工资%d", pe1->name,pe1->age, pe1->salary);
}


    //typedef struct
    //{
    //    __IO uint32_t CRL;
    //    __IO uint32_t CRH;
    //    __IO uint32_t IDR;
    //    __IO uint32_t ODR;
    //    __IO uint32_t BSRR;
    //    __IO uint32_t BRR;
    //    __IO uint32_t LCKR;
    //} GPIO_TypeDef;

//#define GPIOA               ((GPIO_TypeDef *) GPIOA_BASE) //强制转化GPIOA为结构体指针
//#define GPIOB               ((GPIO_TypeDef *) GPIOB_BASE)
// 
// #define GPIOA_BASE            (APB2PERIPH_BASE + 0x0800)
//#define APB2PERIPH_BASE       (PERIPH_BASE + 0x10000)
// #define PERIPH_BASE           ((uint32_t)0x40000000) /*!< Peripheral base address in the alias region */ 指向外围设备的基地址

定义串口自测试

#include "stm32f10x.h"




 void Delay(u32 count)
 {
   u32 i=0;
   for(;i<count;i++);
 }
 
void My_USART1_Init(void)
{
	//GPIO初始化结构体
	GPIO_InitTypeDef GPIO_InitStruct;
	
	USART_InitTypeDef USART_InitStruct;
	
	NVIC_InitTypeDef  NVIC_InitStruct;
	

	
	//串口和IO口的时钟使能
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); //变量,进入assert_param ① 使能相应的时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
	
	//GPIOA 9初始化 IO口初始化
	GPIO_InitStruct.GPIO_Mode= GPIO_Mode_AF_PP; //推挽复用输出
	GPIO_InitStruct.GPIO_Pin=GPIO_Pin_9; //输出引脚
	GPIO_InitStruct.GPIO_Speed=GPIO_Speed_10MHz;
	
	GPIO_Init(GPIOA,&GPIO_InitStruct); //② 初始化IO口
	
	
	//GPIOA 10初始化 IO口初始化
	GPIO_InitStruct.GPIO_Mode= GPIO_Mode_IN_FLOATING; //浮空输出输出
	GPIO_InitStruct.GPIO_Pin=GPIO_Pin_10; //输出引脚
	GPIO_InitStruct.GPIO_Speed=GPIO_Speed_10MHz; 
	
	GPIO_Init(GPIOA,&GPIO_InitStruct); //结构体,进入结构体类型  //② 初始化IO口
	
	//USART_TypeDef* USARTx, USART_InitTypeDef* USART_InitStruct
	
	//9600 N 8 1设置 
	USART_InitStruct.USART_BaudRate=9600;
	USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //不使用硬件流控制
	USART_InitStruct.USART_Mode=USART_Mode_Rx|USART_Mode_Tx; //发送接收都使能
	USART_InitStruct.USART_Parity= USART_Parity_No;  //校验位,0 //在参数搜索进入头文件,在函数形参搜索进入源文件->头文件
	USART_InitStruct.USART_WordLength = USART_WordLength_8b; //数据位,8
	USART_InitStruct.USART_StopBits = USART_StopBits_1;
	
	//串口初始化
	USART_Init(USART1, &USART_InitStruct); //③ 初始化串口参数
	
	//串口使能
	USART_Cmd(USART1,ENABLE); //④ 使能串口
	
	//中断
	USART_ITConfig(USART1,USART_IT_RXNE,ENABLE); //接收缓冲区非空,⑤开启接收中断
	
	NVIC_InitStruct.NVIC_IRQChannel=USART1_IRQn;
	NVIC_InitStruct.NVIC_IRQChannelCmd=ENABLE; //开启中断通道
	NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority=1; //抢占优先级
	NVIC_InitStruct.NVIC_IRQChannelSubPriority=1; //响应优先级
	NVIC_Init(&NVIC_InitStruct);//设置中断优先级
	
}

void USART1_IRQHandler(void) //中断服务函数
{
	u8 res;
	if(USART_GetITStatus(USART1,USART_IT_RXNE))
	{
		res = USART_ReceiveData(USART1);
		
		USART_SendData(USART1,res);
	}
}
 int main(void)
 {	
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//中断优先级 系统优先级设置为2 ,2位抢占,2位响应
	My_USART1_Init();
	while(1);
	 
 }

串口实验:

#include "sys.h"
#include "usart.h"	  
// 	 
//如果使用ucos,则包括下面的头文件即可.
#if SYSTEM_SUPPORT_OS
#include "includes.h"					//ucos 使用	  
#endif
//	 

//V1.5修改说明
//1,增加了对UCOSII的支持
// 	  
 

//
//加入以下代码,支持printf函数,而不需要选择use MicroLIB	  
#if 1
#pragma import(__use_no_semihosting)             
//标准库需要的支持函数                 
struct __FILE 
{ 
	int handle; 

}; 

FILE __stdout;       
//定义_sys_exit()以避免使用半主机模式    
_sys_exit(int x) 
{ 
	x = x; 
} 
//重定义fputc函数 
int fputc(int ch, FILE *f)
{      
	while((USART1->SR&0X40)==0);//循环发送,直到发送完毕   
    USART1->DR = (u8) ch;      
	return ch;
}
#endif 

/*使用microLib的方法*/
 /* 
int fputc(int ch, FILE *f)
{
	USART_SendData(USART1, (uint8_t) ch);

	while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET) {}	
   
    return ch;
}
int GetKey (void)  { 

    while (!(USART1->SR & USART_FLAG_RXNE));

    return ((int)(USART1->DR & 0x1FF));
}
*/
 
#if EN_USART1_RX   //如果使能了接收
//串口1中断服务程序
//注意,读取USARTx->SR能避免莫名其妙的错误   	
u8 USART_RX_BUF[USART_REC_LEN];     //接收缓冲,最大USART_REC_LEN个字节. 200
//接收状态
//bit15,	接收完成标志
//bit14,	接收到0x0d
//bit13~0,	接收到的有效字节数目
u16 USART_RX_STA=0;       //接收状态标记	  
  
void uart_init(u32 bound){
  //GPIO端口设置
  GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;
	 
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE);	//使能USART1,GPIOA时钟
  
	//USART1_TX   GPIOA.9
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;	//复用推挽输出 TX
  GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.9
   
  //USART1_RX	  GPIOA.10初始化
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//PA10
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入 RX
  GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.10  

  //Usart1 NVIC 配置
  NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;//抢占优先级3
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;		//子优先级3
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			//IRQ通道使能
	NVIC_Init(&NVIC_InitStructure);	//根据指定的参数初始化VIC寄存器
  
   //USART 初始化设置

	USART_InitStructure.USART_BaudRate = bound;//串口波特率
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
	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); //初始化串口1
  USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启串口接受中断
  USART_Cmd(USART1, ENABLE);                    //使能串口1 

}

void USART1_IRQHandler(void)                	//串口1中断服务程序
	{
	u8 Res; //
#if SYSTEM_SUPPORT_OS 		//如果SYSTEM_SUPPORT_OS为真,则需要支持OS.
	OSIntEnter();    
#endif
	if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)  //接收中断(接收到的数据必须是0x0d 0x0a结尾)
		{
		Res =USART_ReceiveData(USART1);	//读取接收到的数据 一个字节一个字节接收
		//bit15 接收完成标志
		//bit14 接收到0x0D标志  回车:0x0D 换行:0x0A  0x0D=>0100  0x0D+0x0A=>1100 
		//bit13-0 有效数据
		if((USART_RX_STA&0x8000)==0)//接收未完成             1000 0000 0000 0000
			{
			if(USART_RX_STA&0x4000)//上次接收到了0x0d回车     0100 0000 0000 0000
				{
				if(Res!=0x0a)USART_RX_STA=0;//接收错误,重新开始  本次接收数据不是0x0a换行:  Res是8位 
				else USART_RX_STA|=0x8000;	//接收完成了 (回车+换行)     1000 0000 0000 0000 最高位设置为1
				}
			else //还没收到0X0D
				{	
				if(Res==0x0d)USART_RX_STA|=0x4000; //0100 0000 0000 0000 bit14置位为1
				else
					{
					USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ; //0011 1111 1111 1111 确定长度 前13位有效 //u8 BUF缓冲  u16 STA标志 
					USART_RX_STA++;
					if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;//接收数据错误,重新开始接收	  
					}		 
				}
			}   		 
     } 
#if SYSTEM_SUPPORT_OS 	//如果SYSTEM_SUPPORT_OS为真,则需要支持OS.
	OSIntExit();  											 
#endif
} 
#endif	


#include "led.h"
#include "delay.h"
#include "key.h"
#include "sys.h"
#include "usart.h"
 
 
/************************************************

************************************************/


 int main(void)
 {		
 	u16 t;  
	u16 len;	
	u16 times=0;
	delay_init();	    	 //延时函数初始化	  
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
	uart_init(9600);	 //串口初始化为9600
 	LED_Init();			     //LED端口初始化
	KEY_Init();          //初始化与按键连接的硬件接口
 	while(1)
	{
		if(USART_RX_STA&0x8000) //判断最高位
		{					   
			len=USART_RX_STA&0x3fff;//得到此次接收到的数据长度
			printf("\r\n您发送的消息为:\r\n\r\n");
			for(t=0;t<len;t++)
			{
				USART_SendData(USART1, USART_RX_BUF[t]);//向串口1发送数据
				while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET);//等待发送结束
			}
			printf("\r\n\r\n");//插入换行
			USART_RX_STA=0;
		}else
		{
			times++;
			if(times%5000==0)
			{
				printf("\r\n串口实验\r\n");
				printf("ZGZG@ALIENTEK\r\n\r\n");
			}
			if(times%200==0)printf("请输入数据,以回车键结束\n");  
			if(times%30==0)LED0=!LED0;//闪烁LED,提示系统正在运行.
			delay_ms(10);   
		}
	}	 
 }


外部中断实验:

#include "exti.h"
#include "led.h"
#include "key.h"
#include "delay.h"
#include "usart.h"
#include "beep.h"

//	 
  
//   
//外部中断0服务程序
void EXTIX_Init(void)
{
	/*
	1,初始化IO口为输入
	GPIO_Init();
	
	2,开启IO口复用时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
	
	3,设置IO口与中断线的映射关系
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOE,GPIO_PinSource2);
	
	4,初始化线上中断,设置触发条件等
	EXTI_Init(&EXTI_InitStructure);
	
	5,配置中断分组(NVIC),并使能中断
	NVIC_Init(&NVIC_InitStructure); 
	
	6,编写中断服务函数
	EXTI0_IRQHandler(void)
	
	7,清除中断标志位
	EXTI_ClearITPendingBit(EXTI_Line0)
	*/
 
 	EXTI_InitTypeDef EXTI_InitStructure;
 	NVIC_InitTypeDef NVIC_InitStructure;

    KEY_Init();	 //	按键端口初始化 默认为GPIO_Mode_IPU = 0x48, 上拉

  	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);	//使能复用功能时钟 APB2的外设时钟

    //GPIOE.2 中断线以及中断初始化配置   下降沿触发
	/*
	GPIO_Pin_4和GPIO_PinSource4,GPIO_Pin_4是每个引脚对应的相对于GPIOA~GPIOG的基地址的对应地址变化,
	而GPIO_PinSource4是在引脚复用时的对应的复用序列号,
	因为每组引脚都对应着16种复用序号,所以GPIO_PinSource4对应的地址号0x04就是第五个复用序号,
	因为是从零开始的。代表的是顺序号。和GPIO_Pin_4不一样。
	
	PA0
	PB0 7个   => ExTi0
	...
	PG0
	
	PA1
	PB1 7个   => ExTi1
	...
	PG1
	
	...
	
	PA15
	PB15 7个   => ExTi15
	...
	PG15
	总共有16*7=112个映射  16个中断线
	
	但同一时间只能一个IO口映射到一个中断线
	
	#define KEY0  GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_4)//读取按键0
	#define KEY1  GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_3)//读取按键1
	#define KEY2  GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_2)//读取按键2 
	#define WK_UP   GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0)//读取按键3(WK_UP) 
	*/
  	GPIO_EXTILineConfig(GPIO_PortSourceGPIOE,GPIO_PinSource2); //定义在stm32f10x_gpio.h ,STM32的IO口使用了PE,对应中断线为ExTi4

	//初始化外部中断线
  	EXTI_InitStructure.EXTI_Line=EXTI_Line2;	//KEY2
  	EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;	
  	EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
  	EXTI_InitStructure.EXTI_LineCmd = ENABLE;
  	EXTI_Init(&EXTI_InitStructure);	 	//根据EXTI_InitStruct中指定的参数初始化外设EXTI寄存器

   //GPIOE.3	  中断线以及中断初始化配置 下降沿触发 //KEY1
  	GPIO_EXTILineConfig(GPIO_PortSourceGPIOE,GPIO_PinSource3); //端口GPIO_PortSourceGPIOE 外部线GPIO_PinSource3
  	EXTI_InitStructure.EXTI_Line=EXTI_Line3;
  	EXTI_Init(&EXTI_InitStructure);	  	//根据EXTI_InitStruct中指定的参数初始化外设EXTI寄存器

   //GPIOE.4	  中断线以及中断初始化配置  下降沿触发	//KEY0
  	GPIO_EXTILineConfig(GPIO_PortSourceGPIOE,GPIO_PinSource4);
  	EXTI_InitStructure.EXTI_Line=EXTI_Line4;
  	EXTI_Init(&EXTI_InitStructure);	  	//根据EXTI_InitStruct中指定的参数初始化外设EXTI寄存器


   //GPIOA.0	  中断线以及中断初始化配置 上升沿触发 PA0  WK_UP
 	 GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource0); 

  	EXTI_InitStructure.EXTI_Line=EXTI_Line0;
  	EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
  	EXTI_Init(&EXTI_InitStructure);		//根据EXTI_InitStruct中指定的参数初始化外设EXTI寄存器


  	NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;			//使能按键WK_UP所在的外部中断通道
  	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02;	//抢占优先级2, 
  	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x03;					//子优先级3
  	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;								//使能外部中断通道
  	NVIC_Init(&NVIC_InitStructure); 

    NVIC_InitStructure.NVIC_IRQChannel = EXTI2_IRQn;			//使能按键KEY2所在的外部中断通道
  	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02;	//抢占优先级2, 
  	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02;					//子优先级2
  	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;								//使能外部中断通道
  	NVIC_Init(&NVIC_InitStructure);


  	NVIC_InitStructure.NVIC_IRQChannel = EXTI3_IRQn;			//使能按键KEY1所在的外部中断通道
  	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02;	//抢占优先级2 
  	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x01;					//子优先级1 
  	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;								//使能外部中断通道
  	NVIC_Init(&NVIC_InitStructure);  	  //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器

	NVIC_InitStructure.NVIC_IRQChannel = EXTI4_IRQn;			//使能按键KEY0所在的外部中断通道
  	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02;	//抢占优先级2 
  	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x00;					//子优先级0 
  	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;								//使能外部中断通道
  	NVIC_Init(&NVIC_InitStructure);  	  //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器
 
}

//外部中断0服务程序 
void EXTI0_IRQHandler(void)
{
	delay_ms(10);//消抖
	if(WK_UP==1)	 	 //WK_UP按键 GPIOA
	{				 
		BEEP=!BEEP;	
	}
	EXTI_ClearITPendingBit(EXTI_Line0); //清除LINE0上的中断标志位  
}
 
//外部中断2服务程序
void EXTI2_IRQHandler(void)
{
	delay_ms(10);//消抖
	if(KEY2==0)	  //按键KEY2
	{
		LED0=!LED0;
	}		 
	EXTI_ClearITPendingBit(EXTI_Line2);  //清除LINE2上的中断标志位  
}
//外部中断3服务程序
void EXTI3_IRQHandler(void)
{
	delay_ms(10);//消抖
	if(KEY1==0)	 //按键KEY1
	{				 
		LED1=!LED1;
	}		 
	EXTI_ClearITPendingBit(EXTI_Line3);  //清除LINE3上的中断标志位  
}

void EXTI4_IRQHandler(void)
{
	delay_ms(10);//消抖
	if(KEY0==0)	 //按键KEY0
	{
		LED0=!LED0;
		LED1=!LED1; 
	}		 
	EXTI_ClearITPendingBit(EXTI_Line4);  //清除LINE4上的中断标志位  
}
 

#include "stm32f10x.h"
#include "key.h"
#include "sys.h" 
#include "delay.h"
//	 
					  
//  
								    
//按键初始化函数
void KEY_Init(void) //IO初始化
{ 
 	GPIO_InitTypeDef GPIO_InitStructure;
 
 	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOE,ENABLE);//使能PORTA,PORTE时钟

	GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4;//KEY0-KEY2
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //设置成上拉输入
 	GPIO_Init(GPIOE, &GPIO_InitStructure);//初始化GPIOE2,3,4

	//初始化 WK_UP-->GPIOA.0	  下拉输入
	GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_0;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; //PA0设置成输入,默认下拉	  
	GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.0

}
//按键处理函数
//返回按键值
//mode:0,不支持连续按;1,支持连续按;
//0,没有任何按键按下
//1,KEY0按下
//2,KEY1按下
//3,KEY2按下 
//4,KEY3按下 WK_UP
//注意此函数有响应优先级,KEY0>KEY1>KEY2>KEY3!!
u8 KEY_Scan(u8 mode)
{	 
	static u8 key_up=1;//按键按松开标志
	if(mode)key_up=1;  //支持连按		  
	if(key_up&&(KEY0==0||KEY1==0||KEY2==0||WK_UP==1))
	{
		delay_ms(10);//去抖动 
		key_up=0;
		if(KEY0==0)return KEY0_PRES;
		else if(KEY1==0)return KEY1_PRES;
		else if(KEY2==0)return KEY2_PRES;
		else if(WK_UP==1)return WKUP_PRES;
	}else if(KEY0==1&&KEY1==1&&KEY2==1&&WK_UP==0)key_up=1; 	    
 	return 0;// 无按键按下
}

#include "led.h"
#include "delay.h"
#include "key.h"
#include "sys.h"
#include "usart.h"
#include "exti.h"
#include "beep.h"

 
/************************************************

************************************************/

 int main(void)
 {		
 
	delay_init();	    	 //延时函数初始化	  
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
	uart_init(115200);	 //串口初始化为115200
 	LED_Init();		  		//初始化与LED连接的硬件接口
	BEEP_Init();         	//初始化蜂鸣器端口
	KEY_Init();         	//初始化与按键连接的硬件接口
	EXTIX_Init();		 	//外部中断初始化
	LED0=0;					//点亮LED0
	while(1)
	{	    
		printf("OK\r\n");	
		delay_ms(1000);	  
	}
 }


定时器

#include "timer.h"
#include "led.h"
//	 

//   	 

//通用定时器3中断初始化
//这里时钟选择为APB1的2倍,而APB1为36M
//arr:自动重装值。
//psc:时钟预分频数
//这里使用的是定时器3!

/*
1,使能定时器时钟

RCC_APB1PeriphClockCmd()

2,初始化定时器,配置ARR自动重装载寄存器周期的值, PSC: 设置用来作为TIMx时钟频率除数的预分频值

TIM_TimeBaseInit()

3,开启定时器中断配置NVIC

Void TIM_ITConfig()
NVIC_Init()

4,使能定时器

TIM_Cmd()


先说结论, TIM3_Int_Init(5000-1,8400-1)这一句是0.5s进入一次的中断。
中断代码,8400是分频系数,5000是预装载值。我们使用的是TIM3.
根据时钟树,可以知道TIM3挂载在APB1下,APB1的时钟频率是=42MHZ,但是因为分频系数不等于1,所以TIM3的时钟为APB1的频率*2=84MHZ。

*/


void TIM3_Int_Init(u16 arr,u16 psc)
{
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
	NVIC_InitTypeDef NVIC_InitStructure;

	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //1,时钟使能
	
	/*
	voidTIM_TimeBaseInit(TIM_TypeDef*TIMx, TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct);
	
	第一个参数是确定是哪个定时器
	第二个参数是定时器初始化参数结构体指针,结构体类型为 TIM_TimeBaseInitTypeDef
	
	typedef struct
	{
	uint16_t TIM_Prescaler;
	uint16_t TIM_CounterMode;
	uint16_t TIM_Period;
	uint16_t TIM_ClockDivision;
	uint8_t TIM_RepetitionCounter;
	} TIM_TimeBaseInitTypeDef;
	
	对于通用定时器只有前面四个参数有用,最后一个参数 TIM_RepetitionCounter 是高级定时器才有用的
	第一个参数 TIM_Prescaler 是用来设置分频系数
	第二个参数 TIM_CounterMode 是用来设置计数方式
	第三个参数是设置自动重载计数周期值
	第四个参数是用来设置时钟分频因子
	*/
	

	
	//定时器TIM3初始化
	TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值, 传入值	
	TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值, 传入值
	TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割:TDTS = Tck_tim
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式
	
	TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //2,根据指定的参数初始化TIMx的时间基数单位
 
	TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE ); //3,使能指定的TIM3中断,允许更新中断

	//中断优先级NVIC设置
	NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;  //TIM3中断
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;  //先占优先级0级
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;  //从优先级3级
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
	NVIC_Init(&NVIC_InitStructure);  //3, 初始化NVIC寄存器


	TIM_Cmd(TIM3, ENABLE);  //4, 使能TIMx					 
}
//定时器3中断服务程序
void TIM3_IRQHandler(void)   //TIM3中断
{
	if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET)  //检查TIM3更新中断发生与否
		{
		TIM_ClearITPendingBit(TIM3, TIM_IT_Update  );  //清除TIMx更新中断标志 
		LED1=!LED1;
		}
}

#include "led.h"
#include "delay.h"
#include "key.h"
#include "sys.h"
#include "usart.h"
#include "timer.h"
 

/************************************************

************************************************/


#include "led.h"
#include "delay.h"
#include "key.h"
#include "sys.h"
#include "usart.h"
#include "timer.h"
 

/************************************************

************************************************/


 int main(void)
 {		
 
	delay_init();	    	 //延时函数初始化	  
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
	uart_init(115200);	 //串口初始化为115200
 	LED_Init();			     //LED端口初始化
	 
	 //10Khz的计数频率,
	 //u16 arr 设置在下一个更新事件装入活动的自动重装载寄存器周期的值	 计数到5000为500ms u16 psc 设置用来作为TIMx时钟频率除数的预分频值  10Khz的计数频率  u16 arr,u16 psc
	TIM3_Int_Init(4999,7199);
   	while(1)
	{
		LED0=!LED0;
		delay_ms(200);		   
	}	 

 
}	 
 


 
}	 
 

PWM实验

#include "timer.h"
#include "led.h"
//	 

//   	 

//通用定时器3中断初始化
//这里时钟选择为APB1的2倍,而APB1为36M
//arr:自动重装值。
//psc:时钟预分频数
//这里使用的是定时器3!

/*
1,使能定时器时钟

RCC_APB1PeriphClockCmd()

2,初始化定时器,配置ARR自动重装载寄存器周期的值, PSC: 设置用来作为TIMx时钟频率除数的预分频值

TIM_TimeBaseInit()

3,开启定时器中断配置NVIC

Void TIM_ITConfig()
NVIC_Init()

4,使能定时器

TIM_Cmd()


先说结论, TIM3_Int_Init(5000-1,8400-1)这一句是0.5s进入一次的中断。
中断代码,8400是分频系数,5000是预装载值。我们使用的是TIM3.
根据时钟树,可以知道TIM3挂载在APB1下,APB1的时钟频率是=42MHZ,但是因为分频系数不等于1,所以TIM3的时钟为APB1的频率*2=84MHZ。

*/


//

	/*
	#define IS_GPIO_MODE(MODE) (((MODE) == GPIO_Mode_AIN) || ((MODE) == GPIO_Mode_IN_FLOATING) || \ //模拟输入  //浮空输入
                            ((MODE) == GPIO_Mode_IPD) || ((MODE) == GPIO_Mode_IPU) || \             //输入下拉   //输入上拉
                            ((MODE) == GPIO_Mode_Out_OD) || ((MODE) == GPIO_Mode_Out_PP) || \       //开漏输出    //推挽式输出
                            ((MODE) == GPIO_Mode_AF_OD) || ((MODE) == GPIO_Mode_AF_PP))             //开漏复用输出  //推挽式复用输出
	16*7(ABCDEFG)=112个IO
	#define IS_GET_GPIO_PIN(PIN) (((PIN) == GPIO_Pin_0) || \
                              ((PIN) == GPIO_Pin_1) || \
                              ((PIN) == GPIO_Pin_2) || \
                              ((PIN) == GPIO_Pin_3) || \
                              ((PIN) == GPIO_Pin_4) || \
                              ((PIN) == GPIO_Pin_5) || \
                              ((PIN) == GPIO_Pin_6) || \
                              ((PIN) == GPIO_Pin_7) || \
                              ((PIN) == GPIO_Pin_8) || \
                              ((PIN) == GPIO_Pin_9) || \
                              ((PIN) == GPIO_Pin_10) || \
                              ((PIN) == GPIO_Pin_11) || \
                              ((PIN) == GPIO_Pin_12) || \
                              ((PIN) == GPIO_Pin_13) || \
                              ((PIN) == GPIO_Pin_14) || \
                              ((PIN) == GPIO_Pin_15))

	*/




/*
1,使能定时器3和相关的IO口时钟

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //使能定时器 3 时钟.

库函数使能 TIM3 时钟的方法是:
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); //复用时钟使能 设置 PB5(GPIO B 在APB2上) 为复用功能输出


APB1 上面连接的是低速外设,包括电源接口、备份接口、CAN、USB、I2C1、I2C2、UART2、UART3 等等,

APB2 上面连接的是高速外设包括 UART1、SPI1、Timer1、ADC1、ADC2、所有普通 IO 口(PA~PE)、第二功能 IO 口等

APB1负责DA,串口2,3,4,5,普通定时器TIM2-7, USB , IIC  , CAN
APB2负责AD(ADC1,2,3),I/O,串口1,高级定时器TIM1,TIM8, GPIOA,GPIOB


TIM3_CH2 默认是接在 PA7上面 ,需要重映射配置到 PB5  为复用输出。
要使用 TIM3,我们必须先开启 TIM3 的时钟 这是因为 TIM3_CH2 通道将重映射到 PB5 上,此时,PB5
属于复用功能输出。



2,初始化IO口为复用功能输出。函数GPIO_Init();
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;

3,需要把PB5作为定时器的PWM输出引脚,所以要重映射配置,需要开启AFIO时钟,同时设置重映射。

RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
GPIO_PinRemapConfig(GPIO_PartialRemap_Tim3,ENABLE);

4,初始化定时器,ARR,PSC等
TIM_TimeBaseInit();

5,初始化输出比较参数:TIM_OC2Init();

6,使能预装载寄存器: TIM_OC2PreloadConfig(TIM3,TIM_OC2Preload_Enable);

7,使能定时器。 TIM_Cmd();

8,不断改变比较值CCRx,达到不同的占空比效果:TIM_SetCompare2();
*/



void TIM3_PWM_Init(u16 arr,u16 psc)
{

	
	//定义GPIO初始化结构体
	GPIO_InitTypeDef GPIO_InitStructrue;
	
	//定时器结构体
	TIM_TimeBaseInitTypeDef TIM_TimeBaseStructrue;
	
	//PWM 通道设置结构体
	TIM_OCInitTypeDef TIM_OCInitStructrue;
	
	//1,时钟使能
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE); //使能定时器3时钟 参数:复用功能时钟,使能
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_AFIO,ENABLE); //使能GPIO外设和AFIO复用功能模块时钟 或运算:2个都初始化
	
	//2,初始化IO口为复用功能输出。函数GPIO_Init();
	//GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;
	
	GPIO_InitStructrue.GPIO_Pin=GPIO_Pin_5; //LED->PB.5 端口配置  //指定IO口
	
	GPIO_InitStructrue.GPIO_Mode= GPIO_Mode_AF_PP; // 指定IO口模式(8种IO口模式中的1种) 复用推挽输出
	
	GPIO_InitStructrue.GPIO_Speed=GPIO_Speed_50MHz; //指定IO口的速度
	
	GPIO_Init(GPIOB,&GPIO_InitStructrue);
	
	//3,需要把PB5作为定时器的PWM输出引脚,所以要重映射配置,需要开启AFIO时钟,同时设置重映射。
		//RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
		//GPIO_PinRemapConfig(GPIO_PartialRemap_Tim3,ENABLE);

	GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3,ENABLE); //定时器3部分重映射GPIO_PartialRemap_TIM3
	
	//4,初始化定时器,ARR,PSC等
	//TIM_TimeBaseInit();
	
	/*
		uint16_t TIM_Prescaler;  
		uint16_t TIM_CounterMode;
		uint16_t TIM_Period;  
		uint16_t TIM_ClockDivision; 
		uint8_t TIM_RepetitionCounter;
	*/
	
	TIM_TimeBaseStructrue.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器的周期的值
	TIM_TimeBaseStructrue.TIM_RepetitionCounter = psc; //设置用来作为TIMX时钟
	TIM_TimeBaseStructrue.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割:TDTS=Tck_tim
	TIM_TimeBaseStructrue.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式

	TIM_TimeBaseInit(TIM3,&TIM_TimeBaseStructrue); //根据指定的参数初始化TIMx的时间基数单位
	
	
	//5,初始化输出比较参数:TIM_OC2Init(); PWM 通道设置
	//参数 TIM_OCMode 设置模式是 PWM 还是输出比较,这里是 PWM 模式。
	//参数 TIM_OutputState 用来设置比较输出使能,也就是使能 PWM 输出到端口。
	//参数 TIM_OCPolarity 用来设置极性是高还是低。
	TIM_OCInitStructrue.TIM_OCMode=TIM_OCMode_PWM2; //选择 PWM 模式 2
	TIM_OCInitStructrue.TIM_OCPolarity=TIM_OCPolarity_High; //输出极性高
	TIM_OCInitStructrue.TIM_OutputState= TIM_OutputState_Enable; //比较输出使能
	
	TIM_OC2Init(TIM3,&TIM_OCInitStructrue);
	
	//6,使能预装载寄存器: TIM_OC2PreloadConfig(TIM3,TIM_OC2Preload_Enable);
	
	TIM_OC2PreloadConfig(TIM3,TIM_OCPreload_Enable);//使能预装载寄存器

	//7,使能定时器。 TIM_Cmd();
	
	TIM_Cmd(TIM3, ENABLE);

	//8,不断改变比较值CCRx,达到不同的占空比效果:TIM_SetCompare2(); 主函数中
}	



}	

#include "led.h"
#include "delay.h"
#include "key.h"
#include "sys.h"
#include "usart.h"
#include "timer.h"
 

/************************************************
从死循环函数可以看出,将 led0pwmval 这个值设置为 PWM 比较值,也就
是通过 led0pwmval 来控制 PWM 的占空比,然后控制 led0pwmval 的值从 0 变到 300,然后又
从 300 变到 0,如此循环,因此 DS0 的亮度也会跟着从暗变到亮,然后又从亮变到暗。至于这
里的值,我们为什么取 300,是因为 PWM 的输出占空比达到这个值的时候,我们的 LED 亮度
变化就不大了(虽然最大值可以设置到 899),因此设计过大的值在这里是没必要的。
************************************************/


 int main(void)
 {		
 	u16 led0pwmval=0;
	u8 dir=1;	
	delay_init();	    	 //延时函数初始化	  
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); 	 //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
	uart_init(115200);	 //串口初始化为115200
 	LED_Init();			     //LED端口初始化
 	TIM3_PWM_Init(899,0);	 //不分频。PWM频率=72000000/900=80Khz
   	while(1)
	{
 		delay_ms(10);	 
		if(dir)led0pwmval++;
		else led0pwmval--;

 		if(led0pwmval>300)dir=0;
		if(led0pwmval==0)dir=1;										 
		TIM_SetCompare2(TIM3,led0pwmval);	//LED灯低电平有效,不断改变占空比,改变灯的亮度
	}	 
 }
 

I2C实验:

#include "myiic.h"
#include "delay.h"
//	 
								  
//
 
//初始化IIC
void IIC_Init(void)
{					     
	GPIO_InitTypeDef GPIO_InitStructure;
	RCC_APB2PeriphClockCmd(	RCC_APB2Periph_GPIOB, ENABLE );	//使能GPIOB时钟
	   
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ;   //推挽输出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStructure);
	GPIO_SetBits(GPIOB,GPIO_Pin_6|GPIO_Pin_7); 	//PB6,PB7 输出高
}
//产生IIC起始信号
void IIC_Start(void)
{
	SDA_OUT();     //sda线输出
	IIC_SDA=1;	  	  
	IIC_SCL=1;
	delay_us(4);
 	IIC_SDA=0;//START:when CLK is high,DATA change form high to low  SCL,SDA全拉高。 SCL为高时, SDA随后拉低,开始
	delay_us(4);
	IIC_SCL=0;//钳住I2C总线,准备发送或接收数据 
}	  
//产生IIC停止信号
void IIC_Stop(void)
{
	SDA_OUT();//sda线输出
	IIC_SCL=0;
	IIC_SDA=0;//STOP:when CLK is high DATA change form low to high  SCL SDA全拉低。 SCL为高之后,SDA也拉高,结束
 	delay_us(4);
	IIC_SCL=1; 
	IIC_SDA=1;//发送I2C总线结束信号
	delay_us(4);							   	
}
//等待应答信号到来
//返回值:1,接收应答失败
//        0,接收应答成功
u8 IIC_Wait_Ack(void)
{
	u8 ucErrTime=0;
	SDA_IN();      //SDA设置为输入  
	IIC_SDA=1;delay_us(1);	   
	IIC_SCL=1;delay_us(1);	 
	while(READ_SDA)  //如果输入线READ_SDA一直为高,则为无应答。
	{
		ucErrTime++;
		if(ucErrTime>250)
		{
			IIC_Stop();
			return 1;
		}
	}
	IIC_SCL=0;//时钟输出0 	    READ_SDA低电平有效
	return 0;  
} 
//产生ACK应答
void IIC_Ack(void)
{
	IIC_SCL=0;
	SDA_OUT();
	IIC_SDA=0;
	delay_us(2); //SCL为高时, SDA一直为低 产生应答 第九个时钟期间
	IIC_SCL=1;
	delay_us(2);
	IIC_SCL=0;
}
//不产生ACK应答		    
void IIC_NAck(void)
{
	IIC_SCL=0;
	SDA_OUT();
	IIC_SDA=1;
	delay_us(2);  
	IIC_SCL=1;
	delay_us(2);  //SCL为高时  SDA一直为高, 不产生应答
	IIC_SCL=0;
}					 				     
//IIC发送一个字节
//返回从机有无应答
//1,有应答
//0,无应答			  
void IIC_Send_Byte(u8 txd)
{                        
    u8 t;   
	SDA_OUT(); 	    
    IIC_SCL=0;//拉低时钟开始数据传输
    for(t=0;t<8;t++)
    {              
        //IIC_SDA=(txd&0x80)>>7;
		if((txd&0x80)>>7)  //发送的数据最高位 右移7位变成第0位。如果 为1,则SDA置为1
			IIC_SDA=1;		//发送1
		else                
			IIC_SDA=0;		//否则发送0
		txd<<=1; 	  
		delay_us(2);   //对TEA5767这三个延时都是必须的
		IIC_SCL=1;      // SCL 为高的时候 发送数据不能变
		delay_us(2); 
		IIC_SCL=0;	    //SCL为低才能变 发信号
		delay_us(2);
    }	 
} 	    
//读1个字节,ack=1时,发送ACK,ack=0,发送nACK   
u8 IIC_Read_Byte(unsigned char ack)
{
	unsigned char i,receive=0;
	SDA_IN();//SDA设置为输入
    for(i=0;i<8;i++ )
	{
        IIC_SCL=0; 
        delay_us(2);
		IIC_SCL=1;   //与上面相反,SCL为高时候读信号
        receive<<=1; //左移一位
        if(READ_SDA)receive++;    //如果READ_SDA为1,则对receive最低位加1
		delay_us(1); 
    }					 
    if (!ack)
        IIC_NAck();//发送nACK
    else
        IIC_Ack(); //发送ACK   
    return receive;
}

#ifndef __MYIIC_H
#define __MYIIC_H
#include "sys.h"
//	 
			  
//

//IO方向设置
 
#define SDA_IN()  {GPIOB->CRL&=0X0FFFFFFF;GPIOB->CRL|=(u32)8<<28;}
#define SDA_OUT() {GPIOB->CRL&=0X0FFFFFFF;GPIOB->CRL|=(u32)3<<28;}

//IO操作函数	 
#define IIC_SCL    PBout(6) //SCL 时钟线
#define IIC_SDA    PBout(7) //SDA  数据线 半双工
#define READ_SDA   PBin(7)  //输入SDA 

//IIC所有操作函数
void IIC_Init(void);                //初始化IIC的IO口				 
void IIC_Start(void);				//发送IIC开始信号
void IIC_Stop(void);	  			//发送IIC停止信号
void IIC_Send_Byte(u8 txd);			//IIC发送一个字节
u8 IIC_Read_Byte(unsigned char ack);//IIC读取一个字节
u8 IIC_Wait_Ack(void); 				//IIC等待ACK信号
void IIC_Ack(void);					//IIC发送ACK信号
void IIC_NAck(void);				//IIC不发送ACK信号

void IIC_Write_One_Byte(u8 daddr,u8 addr,u8 data);
u8 IIC_Read_One_Byte(u8 daddr,u8 addr);	  
#endif

Can通信

#include "can.h"
#include "led.h"
#include "delay.h"
#include "usart.h"
//	 

// 	 
 
//CAN初始化
//tsjw:重新同步跳跃时间单元.范围:CAN_SJW_1tq~ CAN_SJW_4tq
//tbs2:时间段2的时间单元.   范围:CAN_BS2_1tq~CAN_BS2_8tq;
//tbs1:时间段1的时间单元.   范围:CAN_BS1_1tq ~CAN_BS1_16tq
//brp :波特率分频器.范围:1~1024;  tq=(brp)*tpclk1
//波特率=Fpclk1/((tbs1+1+tbs2+1+1)*brp);
//mode:CAN_Mode_Normal,普通模式;CAN_Mode_LoopBack,回环模式;
//Fpclk1的时钟在初始化的时候设置为36M,如果设置CAN_Mode_Init(CAN_SJW_1tq,CAN_BS2_8tq,CAN_BS1_9tq,4,CAN_Mode_LoopBack);
//则波特率为:36M/((8+9+1)*4)=500Kbps
//返回值:0,初始化OK;
//    其他,初始化失败; 
u8 CAN_Mode_Init(u8 tsjw,u8 tbs2,u8 tbs1,u16 brp,u8 mode)
{ 
	GPIO_InitTypeDef 		GPIO_InitStructure; 
	CAN_InitTypeDef        	CAN_InitStructure;
	CAN_FilterInitTypeDef  	CAN_FilterInitStructure;
#if CAN_RX0_INT_ENABLE 
	NVIC_InitTypeDef  		NVIC_InitStructure;
#endif

	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//使能PORTA时钟	                   											 

	RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);//使能CAN1时钟	

	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;	//复用推挽
	GPIO_Init(GPIOA, &GPIO_InitStructure);			//初始化IO

	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;	//上拉输入
	GPIO_Init(GPIOA, &GPIO_InitStructure);			//初始化IO

	//CAN单元设置
	CAN_InitStructure.CAN_TTCM=DISABLE;			//非时间触发通信模式  
	CAN_InitStructure.CAN_ABOM=DISABLE;			//软件自动离线管理	 
	CAN_InitStructure.CAN_AWUM=DISABLE;			//睡眠模式通过软件唤醒(清除CAN->MCR的SLEEP位)
	CAN_InitStructure.CAN_NART=ENABLE;			//禁止报文自动传送 
	CAN_InitStructure.CAN_RFLM=DISABLE;		 	//报文不锁定,新的覆盖旧的  
	CAN_InitStructure.CAN_TXFP=DISABLE;			//优先级由报文标识符决定 
	CAN_InitStructure.CAN_Mode= mode;	        //模式设置: mode:0,普通模式;1,回环模式; 
	//设置波特率
	CAN_InitStructure.CAN_SJW=tsjw;				//重新同步跳跃宽度(Tsjw)为tsjw+1个时间单位  CAN_SJW_1tq	 CAN_SJW_2tq CAN_SJW_3tq CAN_SJW_4tq
	CAN_InitStructure.CAN_BS1=tbs1; 			//Tbs1=tbs1+1个时间单位CAN_BS1_1tq ~CAN_BS1_16tq
	CAN_InitStructure.CAN_BS2=tbs2;				//Tbs2=tbs2+1个时间单位CAN_BS2_1tq ~	CAN_BS2_8tq
	CAN_InitStructure.CAN_Prescaler=brp;        //分频系数(Fdiv)为brp+1	
	CAN_Init(CAN1, &CAN_InitStructure);        	//初始化CAN1 

	CAN_FilterInitStructure.CAN_FilterNumber=0;	//过滤器0
	CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask; 	//屏蔽位模式
	CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit; 	//32位宽 
	CAN_FilterInitStructure.CAN_FilterIdHigh=0x0000;	//32位ID
	CAN_FilterInitStructure.CAN_FilterIdLow=0x0000;
	CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0x0000;//32位MASK
	CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000;
	CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_Filter_FIFO0;//过滤器0关联到FIFO0
	CAN_FilterInitStructure.CAN_FilterActivation=ENABLE;//激活过滤器0

	CAN_FilterInit(&CAN_FilterInitStructure);			//滤波器初始化
	
#if CAN_RX0_INT_ENABLE 
	CAN_ITConfig(CAN1,CAN_IT_FMP0,ENABLE);				//FIFO0消息挂号中断允许.		    

	NVIC_InitStructure.NVIC_IRQChannel = USB_LP_CAN1_RX0_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;     // 主优先级为1
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;            // 次优先级为0
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStructure);
#endif
	return 0;
}   
 
#if CAN_RX0_INT_ENABLE	//使能RX0中断
//中断服务函数			    
void USB_LP_CAN1_RX0_IRQHandler(void)
{
  	CanRxMsg RxMessage;
	int i=0;
    CAN_Receive(CAN1, 0, &RxMessage);
	for(i=0;i<8;i++)
	printf("rxbuf[%d]:%d\r\n",i,RxMessage.Data[i]);
}
#endif

//can发送一组数据(固定格式:ID为0X12,标准帧,数据帧)	
//len:数据长度(最大为8)				     
//msg:数据指针,最大为8个字节.
//返回值:0,成功;
//		 其他,失败;
u8 Can_Send_Msg(u8* msg,u8 len)
{	
	u8 mbox;
	u16 i=0;
	CanTxMsg TxMessage;
	TxMessage.StdId=0x12;			// 标准标识符 
	TxMessage.ExtId=0x12;			// 设置扩展标示符 
	TxMessage.IDE=CAN_Id_Standard; 	// 标准帧
	TxMessage.RTR=CAN_RTR_Data;		// 数据帧
	TxMessage.DLC=len;				// 要发送的数据长度
	for(i=0;i<len;i++)
	TxMessage.Data[i]=msg[i];			          
	mbox= CAN_Transmit(CAN1, &TxMessage);   
	i=0; 
	while((CAN_TransmitStatus(CAN1, mbox)==CAN_TxStatus_Failed)&&(i<0XFFF))i++;	//等待发送结束
	if(i>=0XFFF)return 1;
	return 0;	 
}
//can口接收数据查询
//buf:数据缓存区;	 
//返回值:0,无数据被收到;
//		 其他,接收的数据长度;
u8 Can_Receive_Msg(u8 *buf)
{		   		   
 	u32 i;
	CanRxMsg RxMessage;
    if( CAN_MessagePending(CAN1,CAN_FIFO0)==0)return 0;		//没有接收到数据,直接退出 
    CAN_Receive(CAN1, CAN_FIFO0, &RxMessage);//读取数据	
    for(i=0;i<8;i++)
    buf[i]=RxMessage.Data[i];  
	return RxMessage.DLC;	
}

#include "led.h"
#include "delay.h"
#include "key.h"
#include "sys.h"
#include "lcd.h"
#include "usart.h"	 
#include "can.h" 
 
  
/************************************************

************************************************/


 int main(void)
 {	 
		u8 key;
	u8 i=0,t=0;
	u8 cnt=0;
	u8 canbuf[8];
	u8 res;
	u8 mode=CAN_Mode_LoopBack;//CAN工作模式;CAN_Mode_Normal(0):普通模式,CAN_Mode_LoopBack(1):环回模式

	delay_init();	    	 //延时函数初始化	  
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置中断优先级分组为组2:2位抢占优先级,2位响应优先级
	uart_init(115200);	 	//串口初始化为115200
	LED_Init();		  		//初始化与LED连接的硬件接口
	LCD_Init();			   	//初始化LCD	
	KEY_Init();				//按键初始化		 	
   
	CAN_Mode_Init(CAN_SJW_1tq,CAN_BS2_8tq,CAN_BS1_9tq,4,CAN_Mode_LoopBack);//CAN初始化环回模式,波特率500Kbps    

 	POINT_COLOR=RED;//设置字体为红色 
	LCD_ShowString(60,50,200,16,16,"WarShip STM32");	
	LCD_ShowString(60,70,200,16,16,"CAN TEST");	
	LCD_ShowString(60,90,200,16,16,"ATOM@ALIENTEK");
	LCD_ShowString(60,110,200,16,16,"2015/1/15");
	LCD_ShowString(60,130,200,16,16,"LoopBack Mode");	 
	LCD_ShowString(60,150,200,16,16,"KEY0:Send WK_UP:Mode");//显示提示信息		
	POINT_COLOR=BLUE;//设置字体为蓝色	  
	LCD_ShowString(60,170,200,16,16,"Count:");			//显示当前计数值	
	LCD_ShowString(60,190,200,16,16,"Send Data:");		//提示发送的数据	
	LCD_ShowString(60,250,200,16,16,"Receive Data:");	//提示接收到的数据		
 	while(1)
	{
		key=KEY_Scan(0);
		if(key==KEY0_PRES)//KEY0按下,发送一次数据
		{
			for(i=0;i<8;i++)
			{
				canbuf[i]=cnt+i;//填充发送缓冲区
				if(i<4)LCD_ShowxNum(60+i*32,210,canbuf[i],3,16,0X80);	//显示数据
				else LCD_ShowxNum(60+(i-4)*32,230,canbuf[i],3,16,0X80);	//显示数据
 			}
			res=Can_Send_Msg(canbuf,8);//发送8个字节 
			if(res)LCD_ShowString(60+80,190,200,16,16,"Failed");		//提示发送失败
			else LCD_ShowString(60+80,190,200,16,16,"OK    ");	 		//提示发送成功								   
		}else if(key==WKUP_PRES)//WK_UP按下,改变CAN的工作模式
		{	   
			mode=!mode;
  			CAN_Mode_Init(CAN_SJW_1tq,CAN_BS2_8tq,CAN_BS1_9tq,4,mode);//CAN普通模式初始化, 波特率500Kbps 
			POINT_COLOR=RED;//设置字体为红色 
			if(mode==0)//普通模式,需要2个开发板
			{
				LCD_ShowString(60,130,200,16,16,"Nnormal Mode ");	    
			}else //回环模式,一个开发板就可以测试了.
			{
 				LCD_ShowString(60,130,200,16,16,"LoopBack Mode");
			}
 			POINT_COLOR=BLUE;//设置字体为蓝色 
		}		 
		key=Can_Receive_Msg(canbuf);
		if(key)//接收到有数据
		{			
			LCD_Fill(60,270,130,310,WHITE);//清除之前的显示
 			for(i=0;i<key;i++)
			{									    
				if(i<4)LCD_ShowxNum(60+i*32,270,canbuf[i],3,16,0X80);	//显示数据
				else LCD_ShowxNum(60+(i-4)*32,290,canbuf[i],3,16,0X80);	//显示数据
 			}
		}
		t++; 
		delay_ms(10);
		if(t==20)
		{
			LED0=!LED0;//提示系统正在运行	
			t=0;
			cnt++;
			LCD_ShowxNum(60+48,170,cnt,3,16,0X80);	//显示数据
		}		   
	}
}




.

CAN通信实验:

#include "can.h"
#include "led.h"
#include "delay.h"
#include "usart.h"
//	 

// 	 
 
//CAN初始化
//tsjw:重新同步跳跃时间单元.范围:CAN_SJW_1tq~ CAN_SJW_4tq
//tbs2:时间段2的时间单元.   范围:CAN_BS2_1tq~CAN_BS2_8tq;
//tbs1:时间段1的时间单元.   范围:CAN_BS1_1tq ~CAN_BS1_16tq
//brp :波特率分频器.范围:1~1024;  tq=(brp)*tpclk1
//波特率=Fpclk1/((tbs1+1+tbs2+1+1)*brp);
//mode:CAN_Mode_Normal,普通模式;CAN_Mode_LoopBack,回环模式;
//Fpclk1的时钟在初始化的时候设置为36M,如果设置CAN_Mode_Init(CAN_SJW_1tq,CAN_BS2_8tq,CAN_BS1_9tq,4,CAN_Mode_LoopBack);
//则波特率为:36M/((8+9+1)*4)=500Kbps
//返回值:0,初始化OK;
//    其他,初始化失败; 
u8 CAN_Mode_Init(u8 tsjw,u8 tbs2,u8 tbs1,u16 brp,u8 mode)
{ 
	GPIO_InitTypeDef 		GPIO_InitStructure; 
	CAN_InitTypeDef        	CAN_InitStructure;
	CAN_FilterInitTypeDef  	CAN_FilterInitStructure;
#if CAN_RX0_INT_ENABLE 
	NVIC_InitTypeDef  		NVIC_InitStructure;
#endif

	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//使能PORTA时钟	                   											 

	RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);//使能CAN1时钟	

	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;	//复用推挽
	GPIO_Init(GPIOA, &GPIO_InitStructure);			//初始化IO

	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;	//上拉输入
	GPIO_Init(GPIOA, &GPIO_InitStructure);			//初始化IO

	//CAN单元设置
	CAN_InitStructure.CAN_TTCM=DISABLE;			//非时间触发通信模式  
	CAN_InitStructure.CAN_ABOM=DISABLE;			//软件自动离线管理	 
	CAN_InitStructure.CAN_AWUM=DISABLE;			//睡眠模式通过软件唤醒(清除CAN->MCR的SLEEP位)
	CAN_InitStructure.CAN_NART=ENABLE;			//禁止报文自动传送 
	CAN_InitStructure.CAN_RFLM=DISABLE;		 	//报文不锁定,新的覆盖旧的  
	CAN_InitStructure.CAN_TXFP=DISABLE;			//优先级由报文标识符决定 
	CAN_InitStructure.CAN_Mode= mode;	        //模式设置: mode:0,普通模式;1,回环模式; 
	//设置波特率
	CAN_InitStructure.CAN_SJW=tsjw;				//重新同步跳跃宽度(Tsjw)为tsjw+1个时间单位  CAN_SJW_1tq	 CAN_SJW_2tq CAN_SJW_3tq CAN_SJW_4tq
	CAN_InitStructure.CAN_BS1=tbs1; 			//Tbs1=tbs1+1个时间单位CAN_BS1_1tq ~CAN_BS1_16tq
	CAN_InitStructure.CAN_BS2=tbs2;				//Tbs2=tbs2+1个时间单位CAN_BS2_1tq ~	CAN_BS2_8tq
	CAN_InitStructure.CAN_Prescaler=brp;        //分频系数(Fdiv)为brp+1	
	CAN_Init(CAN1, &CAN_InitStructure);        	//初始化CAN1 

	CAN_FilterInitStructure.CAN_FilterNumber=0;	//过滤器0
	CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask; 	//屏蔽位模式
	CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit; 	//32位宽 
	CAN_FilterInitStructure.CAN_FilterIdHigh=0x0000;	//32位ID
	CAN_FilterInitStructure.CAN_FilterIdLow=0x0000;
	CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0x0000;//32位MASK
	CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000;
	CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_Filter_FIFO0;//过滤器0关联到FIFO0
	CAN_FilterInitStructure.CAN_FilterActivation=ENABLE;//激活过滤器0

	CAN_FilterInit(&CAN_FilterInitStructure);			//滤波器初始化
	
#if CAN_RX0_INT_ENABLE 
	CAN_ITConfig(CAN1,CAN_IT_FMP0,ENABLE);				//FIFO0消息挂号中断允许.		    

	NVIC_InitStructure.NVIC_IRQChannel = USB_LP_CAN1_RX0_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;     // 主优先级为1
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;            // 次优先级为0
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStructure);
#endif
	return 0;
}   
 
#if CAN_RX0_INT_ENABLE	//使能RX0中断
//中断服务函数			    
void USB_LP_CAN1_RX0_IRQHandler(void)
{
  	CanRxMsg RxMessage;
	int i=0;
    CAN_Receive(CAN1, 0, &RxMessage);
	for(i=0;i<8;i++)
	printf("rxbuf[%d]:%d\r\n",i,RxMessage.Data[i]);
}
#endif

//can发送一组数据(固定格式:ID为0X12,标准帧,数据帧)	
//len:数据长度(最大为8)				     
//msg:数据指针,最大为8个字节.
//返回值:0,成功;
//		 其他,失败;
u8 Can_Send_Msg(u8* msg,u8 len)
{	
	u8 mbox;
	u16 i=0;
	CanTxMsg TxMessage;
	TxMessage.StdId=0x12;			// 标准标识符 
	TxMessage.ExtId=0x12;			// 设置扩展标示符 
	TxMessage.IDE=CAN_Id_Standard; 	// 标准帧
	TxMessage.RTR=CAN_RTR_Data;		// 数据帧
	TxMessage.DLC=len;				// 要发送的数据长度
	for(i=0;i<len;i++)
	TxMessage.Data[i]=msg[i];			          
	mbox= CAN_Transmit(CAN1, &TxMessage);   
	i=0; 
	while((CAN_TransmitStatus(CAN1, mbox)==CAN_TxStatus_Failed)&&(i<0XFFF))i++;	//等待发送结束
	if(i>=0XFFF)return 1;
	return 0;	 
}
//can口接收数据查询
//buf:数据缓存区;	 
//返回值:0,无数据被收到;
//		 其他,接收的数据长度;
u8 Can_Receive_Msg(u8 *buf)
{		   		   
 	u32 i;
	CanRxMsg RxMessage;
    if( CAN_MessagePending(CAN1,CAN_FIFO0)==0)return 0;		//没有接收到数据,直接退出 
    CAN_Receive(CAN1, CAN_FIFO0, &RxMessage);//读取数据	
    for(i=0;i<8;i++)
    buf[i]=RxMessage.Data[i];  
	return RxMessage.DLC;	
}

#include "led.h"
#include "delay.h"
#include "key.h"
#include "sys.h"
#include "lcd.h"
#include "usart.h"	 
#include "can.h" 
 
  
/************************************************

************************************************/


 int main(void)
 {	 
		u8 key;
	u8 i=0,t=0;
	u8 cnt=0;
	u8 canbuf[8];
	u8 res;
	u8 mode=CAN_Mode_LoopBack;//CAN工作模式;CAN_Mode_Normal(0):普通模式,CAN_Mode_LoopBack(1):环回模式

	delay_init();	    	 //延时函数初始化	  
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置中断优先级分组为组2:2位抢占优先级,2位响应优先级
	uart_init(115200);	 	//串口初始化为115200
	LED_Init();		  		//初始化与LED连接的硬件接口
	LCD_Init();			   	//初始化LCD	
	KEY_Init();				//按键初始化		 	
   
	CAN_Mode_Init(CAN_SJW_1tq,CAN_BS2_8tq,CAN_BS1_9tq,4,CAN_Mode_LoopBack);//CAN初始化环回模式,波特率500Kbps    

 	POINT_COLOR=RED;//设置字体为红色 
	LCD_ShowString(60,50,200,16,16,"WarShip STM32");	
	LCD_ShowString(60,70,200,16,16,"CAN TEST");	
	LCD_ShowString(60,90,200,16,16,"ATOM@ALIENTEK");
	LCD_ShowString(60,110,200,16,16,"2015/1/15");
	LCD_ShowString(60,130,200,16,16,"LoopBack Mode");	 
	LCD_ShowString(60,150,200,16,16,"KEY0:Send WK_UP:Mode");//显示提示信息		
	POINT_COLOR=BLUE;//设置字体为蓝色	  
	LCD_ShowString(60,170,200,16,16,"Count:");			//显示当前计数值	
	LCD_ShowString(60,190,200,16,16,"Send Data:");		//提示发送的数据	
	LCD_ShowString(60,250,200,16,16,"Receive Data:");	//提示接收到的数据		
 	while(1)
	{
		key=KEY_Scan(0);
		if(key==KEY0_PRES)//KEY0按下,发送一次数据
		{
			for(i=0;i<8;i++)
			{
				canbuf[i]=cnt+i;//填充发送缓冲区
				if(i<4)LCD_ShowxNum(60+i*32,210,canbuf[i],3,16,0X80);	//显示数据
				else LCD_ShowxNum(60+(i-4)*32,230,canbuf[i],3,16,0X80);	//显示数据
 			}
			res=Can_Send_Msg(canbuf,8);//发送8个字节 
			if(res)LCD_ShowString(60+80,190,200,16,16,"Failed");		//提示发送失败
			else LCD_ShowString(60+80,190,200,16,16,"OK    ");	 		//提示发送成功								   
		}else if(key==WKUP_PRES)//WK_UP按下,改变CAN的工作模式
		{	   
			mode=!mode;
  			CAN_Mode_Init(CAN_SJW_1tq,CAN_BS2_8tq,CAN_BS1_9tq,4,mode);//CAN普通模式初始化, 波特率500Kbps 
			POINT_COLOR=RED;//设置字体为红色 
			if(mode==0)//普通模式,需要2个开发板
			{
				LCD_ShowString(60,130,200,16,16,"Nnormal Mode ");	    
			}else //回环模式,一个开发板就可以测试了.
			{
 				LCD_ShowString(60,130,200,16,16,"LoopBack Mode");
			}
 			POINT_COLOR=BLUE;//设置字体为蓝色 
		}		 
		key=Can_Receive_Msg(canbuf);
		if(key)//接收到有数据
		{			
			LCD_Fill(60,270,130,310,WHITE);//清除之前的显示
 			for(i=0;i<key;i++)
			{									    
				if(i<4)LCD_ShowxNum(60+i*32,270,canbuf[i],3,16,0X80);	//显示数据
				else LCD_ShowxNum(60+(i-4)*32,290,canbuf[i],3,16,0X80);	//显示数据
 			}
		}
		t++; 
		delay_ms(10);
		if(t==20)
		{
			LED0=!LED0;//提示系统正在运行	
			t=0;
			cnt++;
			LCD_ShowxNum(60+48,170,cnt,3,16,0X80);	//显示数据
		}		   
	}
}




你可能感兴趣的:(stm32,单片机,arm)