1.uart
(1)一些最基本的原理以及通信方式
首先其工作原理是将数据以串行方式进行发的,接收的时候将数据转换为并行数据。利用异步通信所以不需要时钟线适用于不同芯片、芯片对模块之间的控制。因此需要设置好波特率(115200、9500)数据位、停止位、奇偶效验位。
(2)实际应用中的一些具体操作
在实际应用中不管你是要发数据还是要收数据,首先得拿出一个空余的存储空间出来(buff)对uart进行初始化,首先对其映射的引脚进行初始化,设置波特率,中断的优先级,收或者发、数据位、停止位、奇偶效验位。最后利用定时器或者其他方式一直往buff里面写入数据,并且判断buff是否被填满,填满即可发送给所需要接受的设备即可。
收数据也需初始化上述的一系列操作,就依据发数据时所设定的波特率、数据位、停止位、奇偶效验位,等进行解包读取真实数据。
在我们一般的使用过程之中通常将其封装为8位,第一位和最后一位作为数据包的判断位,第一位如果正确将这个数据包进行解读,解读到最后一位如果也正确就对这个数据获取进行下一步的运用。如果第一位和最后一位有错误则对数据进行丢弃。
(3)具体代码如下
uart.c
#include "sys.h"
#include "usart.h"
#include "led.h"
#include "delay.h"
//
//Èç¹ûʹÓÃucos,Ôò°üÀ¨ÏÂÃæµÄÍ·Îļþ¼´¿É.
RingBuff_t Uart2_RingBuff,Uart1_RingBuff,Uart3_RingBuff;//´´½¨Ò>>¸öringBuffµÄ>>º³åÇø
uint16_t distance = 0;
//¼ÓÈëÒÔÏ´úÂë,Ö§³Öprintfº¯Êý,¶ø²>>ÐèҪѡÔñuse MicroLIB
#if 1
#pragma import(__use_no_semihosting)
//±ê×¼¿âÐèÒªµÄÖ§³Öº¯Êý
struct __FILE
{
int handle;
};
FILE __stdout;
//¶¨Òå_sys_exit()ÒÔ±ÜÃâʹÓðëÖ÷>>úģʽ
void _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
//³õʼ>>¯IO ´®¿Ú1
//bound:²¨ÌØÂÊ
void uart_init(u32 bound){
//GPIO¶Ë¿ÚÉèÖÃ
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE); //ʹÄÜGPIOAʱÖÓ
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);//ʹÄÜUSART1ʱÖÓ
//´®¿Ú1¶ÔÓ¦Òý½Å¸´ÓÃÓ³Éä
GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_USART1); //GPIOA9¸´ÓÃΪUSART1
GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_USART1); //GPIOA10¸´ÓÃΪUSART1
//USART1¶Ë¿ÚÅäÖÃ
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10; //GPIOA9ÓëGPIOA10
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//¸´Óù¦ÄÜ
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //ËÙ¶È50MHz
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //ÍÆÍ츴ÓÃÊä³ö
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //ÉÏÀ
GPIO_Init(GPIOA,&GPIO_InitStructure); //³õʼ>>¯PA9£¬PA10
//USART1 ³õʼ>>¯ÉèÖÃ
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_Cmd(USART1, ENABLE); //ʹÄÜ´®¿Ú1
USART_ClearFlag(USART1, USART_FLAG_TC);
#if EN_USART1_RX
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//¿ªÆôÏà¹ØÖжÏ
//Usart1 NVIC ÅäÖÃ
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;//´®¿Ú1ÖжÏͨµÀ
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0;//ÇÀÕ¼ÓÅÏȼ¶3
NVIC_InitStructure.NVIC_IRQChannelSubPriority =1; //×ÓÓÅÏȼ¶3
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQͨµÀʹÄÜ
NVIC_Init(&NVIC_InitStructure); //¸ù¾ÝÖ¸¶¨µÄ²ÎÊý³õʼ>>¯NVIC¼Ä´æÆ÷
#endif
}
void USART1_IRQHandler(void) //´®¿Ú1ÖжϷþÎñ³ÌÐò
{
uint8_t rdata;
if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
{
rdata = USART_ReceiveData(USART1);
if(Write_RingBuff(&Uart1_RingBuff, rdata) == RINGBUFF_ERR){//>>º³åÇøÂúµÆÁÁ
LED1=0;
}else{
LED1=1;
}
}
}
void uart2_v831_init(uint32_t bound){
//GPIO¶Ë¿ÚÉèÖÃ
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD,ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2,ENABLE);
//´®¿Ú2¶ÔÓ¦Òý½Å¸´ÓÃÓ³Éä
GPIO_PinAFConfig(GPIOD,GPIO_PinSource6,GPIO_AF_USART2);
GPIO_PinAFConfig(GPIOD,GPIO_PinSource5,GPIO_AF_USART2);
//USART1¶Ë¿ÚÅäÖÃ
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_5;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//¸´Óù¦ÄÜ
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //ËÙ¶È50MHz
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //ÍÆÍ츴ÓÃÊä³ö
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //ÉÏÀ
GPIO_Init(GPIOD,&GPIO_InitStructure);
//USART2 ³õʼ>>¯ÉèÖÃ
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(USART2, &USART_InitStructure); //³õʼ>>¯´®¿Ú
USART_Cmd(USART2, ENABLE); //ʹÄÜ´®¿Ú2
USART_ClearFlag(USART2, USART_FLAG_TC);
USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);//¿ªÆôÏà¹ØÖжÏ
//Usart2 NVIC ÅäÖÃ
NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;//´®¿Ú2ÖжÏͨµÀ
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0;//ÇÀÕ¼ÓÅÏȼ¶
NVIC_InitStructure.NVIC_IRQChannelSubPriority =0; //×ÓÓÅÏȼ¶
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQͨµÀʹÄÜ
NVIC_Init(&NVIC_InitStructure); //¸ù¾ÝÖ¸¶¨µÄ²ÎÊý³õʼ>>¯NVIC¼Ä´æÆ÷
}
void USART2_IRQHandler(void) //´®¿Ú2ÖжϷþÎñ³ÌÐò
{
uint8_t rdata;
if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET)
{
rdata = USART_ReceiveData(USART2);
if(Write_RingBuff(&Uart2_RingBuff, rdata) == RINGBUFF_ERR){//>>º³åÇøÂúµÆÁÁ
LED1=0;
}else{
LED1=1;
}
}
}
void uart3_init(uint32_t bound){
//GPIO¶Ë¿ÚÉèÖÃ
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB,ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3,ENABLE);
GPIO_PinAFConfig(GPIOB,GPIO_PinSource10,GPIO_AF_USART3);
GPIO_PinAFConfig(GPIOB,GPIO_PinSource11,GPIO_AF_USART3);
//USART1¶Ë¿ÚÅäÖÃ
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//¸´Óù¦ÄÜ
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //ËÙ¶È50MHz
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //ÍÆÍ츴ÓÃÊä³ö
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //ÉÏÀ
GPIO_Init(GPIOB,&GPIO_InitStructure);
//USART3 ³õʼ>>¯ÉèÖÃ
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(USART3, &USART_InitStructure); //³õʼ>>¯´®¿Ú
USART_Cmd(USART3, ENABLE); //ʹÄÜ´®¿Ú2
USART_ClearFlag(USART3, USART_FLAG_TC);
USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);//¿ªÆôÏà¹ØÖжÏ
//USART3 NVIC ÅäÖÃ
NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;//´®¿Ú2ÖжÏͨµÀ
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1;//ÇÀÕ¼ÓÅÏȼ¶
NVIC_InitStructure.NVIC_IRQChannelSubPriority =0; //×ÓÓÅÏȼ¶
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQͨµÀʹÄÜ
NVIC_Init(&NVIC_InitStructure); //¸ù¾ÝÖ¸¶¨µÄ²ÎÊý³õʼ>>¯NVIC¼Ä´æÆ÷
}
void USART3_IRQHandler(void)
{
uint8_t rdata;
if(USART_GetITStatus(USART3, USART_IT_RXNE) != RESET)
{
rdata = USART_ReceiveData(USART3);
if(Write_RingBuff(&Uart3_RingBuff, rdata) == RINGBUFF_ERR){//>>º³åÇøÂúµÆÁÁ
LED1=0;
}else{
LED1=1;
}
}
}
uint16_t get_distance(void)
{
uint16_t mm = 0;
uint8_t cmd = 0x55;
static uint16_t i;
i++;
if(Uart3_RingBuff.Lenght == 2){
i=0;
uint8_t data = 0;
Read_RingBuff(&Uart3_RingBuff, &data);
mm = data;
Read_RingBuff(&Uart3_RingBuff, &data);
mm = mm << 8 | data;
//delay_us(1000);
usart_send(USART3,&cmd,1);
}
if(i==100 || Uart3_RingBuff.Lenght > 2){ //Ò>>Ãë
RingBuff_Init(&Uart3_RingBuff);
usart_send(USART3,&cmd,1);
}
return mm;
}
uint8_t DataDecode(RingBuff_t *ringbuff, uint8_t *data1, uint8_t *data2)
{
static uint8_t uart_dec_count;
static uint8_t uart_rec_data[5];
uint8_t ret = 1;
if(Read_RingBuff(ringbuff, &uart_rec_data[uart_dec_count]) == RINGBUFF_ERR){
return 1;
}
if((uart_dec_count == 0)&&(uart_rec_data[uart_dec_count] != 0x55)) { //¼ì²âµÚÒ>>¸öÊý¾ÝÊÇ·ñΪ0x55
uart_rec_data[uart_dec_count] = 0;
} else if((uart_dec_count == 1)&&(uart_rec_data[uart_dec_count] != 0xaa)){ //¼ì²âµÚ¶þ¸öÊý¾ÝÊÇ·ñΪ0xaa
uart_rec_data[uart_dec_count] = 0;
uart_rec_data[uart_dec_count-1] = 0;
uart_dec_count = 0;
} else if((uart_dec_count == 4)&&(uart_rec_data[uart_dec_count] != 0xfa)){
uart_rec_data[uart_dec_count] = 0;
uart_rec_data[uart_dec_count-1] = 0;
uart_rec_data[uart_dec_count-2] = 0;
uart_rec_data[uart_dec_count-3] = 0;
uart_rec_data[uart_dec_count-4] = 0;
uart_dec_count = 0;
} else {
if(uart_dec_count == 4)//³É¹¦½ÓÊÕÒ>>Ö¡Êý¾Ý
{
*data1 = uart_rec_data[2];
*data2 = uart_rec_data[3];
ret = 0;
}
uart_dec_count ++;
if(uart_dec_count == 5)
{
uart_dec_count = 0;
}
}
return ret;
}
/* ½ÓÊÕjson×Ö·û´® */
int8_t receiveJson(RingBuff_t *ringbuff, char *str)
{
static uint8_t reading,j;
uint8_t readbuff,ok = 0;
if(Read_RingBuff(&Uart1_RingBuff,&readbuff) == RINGBUFF_OK){
if(readbuff == '{'){
reading = 1;
str[j++] = readbuff;
ok = 0;
}else if(readbuff == '}' && reading == 1){
reading = 0;
str[j++] = readbuff;
str[j++] = '\0';
ok = 1;
}else if(reading == 1){
str[j++] = readbuff;
}else {
j = 0;
reading = 0;
ok = 0;
}
}
return ok;
}
void usart_send(USART_TypeDef* USARTx, uint8_t*data, uint8_t len)
{
uint8_t i;
for(i=0;i<len;i++)
{
while(USART_GetFlagStatus(USARTx,USART_FLAG_TC)==RESET);
USART_SendData(USARTx,data[i]);
}
}
/**
* @brief RingBuff_Init
* @param RingBuff_t *ringbuff
* @return void
* @note ³õʼ>>¯>>·ÐÎ>>º³åÇø
*/
void RingBuff_Init(RingBuff_t *ringbuff)
{
//³õʼ>>¯Ïà¹ØÐÅÏ¢
ringbuff->Head = 0;
ringbuff->Tail = 0;
ringbuff->Lenght = 0;
}
/**
* @brief Write_RingBuff
* @param uint8_t data
* @return FLASE:>>·ÐÎ>>º³åÇøÒÑÂú£¬Ð´Èëʧ°Ü;TRUE:дÈë³É¹¦
* @note Íù>>·ÐÎ>>º³åÇøдÈëuint8_tÀàÐ͵ÄÊý¾Ý
*/
uint8_t Write_RingBuff(RingBuff_t *ringbuff, uint8_t data)
{
if(ringbuff->Lenght >= RINGBUFF_LEN) //ÅжÏ>>º³åÇøÊÇ·ñÒÑÂú
{
return RINGBUFF_ERR;
}
ringbuff->Ring_data[ringbuff->Tail]=data;
ringbuff->Tail = (ringbuff->Tail+1)%RINGBUFF_LEN;//·ÀÖ¹Ô½½ç·Ç·¨·ÃÎÊ
ringbuff->Lenght++;
return RINGBUFF_OK;
}
/**
* @brief Read_RingBuff
* @param uint8_t *rData£¬ÓÃÓÚ±£´æ¶ÁÈ¡µÄÊý¾Ý
* @return FLASE:>>·ÐÎ>>º³åÇøÃ>>ÓÐÊý¾Ý£¬¶Áȡʧ°Ü;TRUE:¶ÁÈ¡³É¹¦
* @note ´Ó>>·ÐÎ>>º³åÇø¶ÁÈ¡Ò>>¸öu8ÀàÐ͵ÄÊý¾Ý
*/
uint8_t Read_RingBuff(RingBuff_t *ringbuff, uint8_t *rData)
{
if(ringbuff->Lenght == 0)//ÅжϷǿÕ
{
return RINGBUFF_ERR;
}
*rData = ringbuff->Ring_data[ringbuff->Head];//ÏȽøÏȳöFIFO£¬´Ó>>º³åÇøÍ·³ö
ringbuff->Head = (ringbuff->Head+1)%RINGBUFF_LEN;//·ÀÖ¹Ô½½ç·Ç·¨·ÃÎÊ
ringbuff->Lenght--;
return RINGBUFF_OK;
}
uart.h
#ifndef __USART_H
#define __USART_H
#include "stdio.h"
#include "stm32f4xx_conf.h"
#include "sys.h"
#define EN_USART1_RX 1 //ʹÄÜ£¨1£©/½ûÖ¹£¨0£©´®¿Ú1½ÓÊÕ
#define RINGBUFF_LEN (100) //¶¨Òå×î´ó½ÓÊÕ×Ö½ÚÊý
#define RINGBUFF_OK 1
#define RINGBUFF_ERR 0
typedef struct
{
uint16_t Head;
uint16_t Tail;
uint16_t Lenght;
uint8_t Ring_data[RINGBUFF_LEN];
}RingBuff_t;
extern uint8_t RecCoorFlag;
extern RingBuff_t Uart2_RingBuff,Uart1_RingBuff,Uart3_RingBuff;
extern uint16_t distance;
void uart_init(u32 bound);
void uart2_v831_init(uint32_t bound);
void uart3_init(uint32_t bound);
void usart_send(USART_TypeDef* USARTx, uint8_t*data, uint8_t len);
void RingBuff_Init(RingBuff_t *ringbuff);
uint8_t Write_RingBuff(RingBuff_t *ringbuff, uint8_t data);
uint8_t Read_RingBuff(RingBuff_t *ringbuff, uint8_t *rData);
uint8_t DataDecode(RingBuff_t *ringbuff, uint8_t *data1, uint8_t *data2);
int8_t receiveJson(RingBuff_t *ringbuff, char *str);
uint16_t get_distance(void);
#endif
2.spi
(1)原理
SPI协议使用四个信号线进行通信:主设备的主输出(MOSI),主输入(MISO),时钟线(SCK)和片选线(SS)。
- 主设备向从设备发送数据:主设备选中一个从设备,通过片选线SS将其选中。然后,主设备通过主输出线(MOSI)将数据发送给从设备。同时,主设备通过时钟线(SCK)提供时钟信号来同步数据传输。
- 主设备接收从设备的数据:主设备向从设备发送时钟信号,从设备通过主输入线(MISO)将数据传输给主设备。
- 数据传输完成后,主设备通过将片选线(SS)拉高来释放从设备。
SPI协议支持全双工通信,意味着主设备和从设备可以同时发送和接收数据。(同步通信、全双工通信方式)
(2)实际操作和注意事项
首先设置成主机模式,然后对于的io口初始化映射即可。设置单向或者双向数据模式、设置spi的数据大小、设置时钟线空闲时候的电平状态,设置数据采样方式,设定波特率,最后使能spi。(也是和uart一样需要将数据存放到一个固定的buff中,然后对其进行下一步的处理或者运用。)我们最常用的spi也就是7zhen0.96寸的oled。
(3)代码
spi.c
void SPI1_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
SPI_InitTypeDef SPI_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);//ʹÄÜGPIOBʱÖÓ
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);//ʹÄÜSPI1ʱÖÓ
//GPIOFB3,4,5³õʼ>>¯ÉèÖÃ
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5;//PB3~5¸´Óù¦ÄÜÊä³ö
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//¸´Óù¦ÄÜ
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//ÍÆÍìÊä³ö
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//ÉÏÀ
GPIO_Init(GPIOB, &GPIO_InitStructure);//³õʼ>>¯
GPIO_PinAFConfig(GPIOB,GPIO_PinSource3,GPIO_AF_SPI1); //PB3¸´ÓÃΪ SPI1
GPIO_PinAFConfig(GPIOB,GPIO_PinSource4,GPIO_AF_SPI1); //PB4¸´ÓÃΪ SPI1
GPIO_PinAFConfig(GPIOB,GPIO_PinSource5,GPIO_AF_SPI1); //PB5¸´ÓÃΪ SPI1
//ÕâÀïÖ>>Õë¶ÔSPI¿Ú³õʼ>>¯
RCC_APB2PeriphResetCmd(RCC_APB2Periph_SPI1,ENABLE);//¸´Î>>SPI1
RCC_APB2PeriphResetCmd(RCC_APB2Periph_SPI1,DISABLE);//Í£Ö¹¸´Î>>SPI1
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; //ÉèÖÃSPIµ¥Ïò>>òÕßË<<ÏòµÄÊý¾Ýģʽ:SPIÉèÖÃΪË<<ÏßË<<ÏòÈ<<Ë<<¹¤
SPI_InitStructure.SPI_Mode = SPI_Mode_Master; //ÉèÖÃSPI¹¤×÷ģʽ:ÉèÖÃΪÖ÷SPI
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; //ÉèÖÃSPIµÄÊý¾Ý´óС:SPI·¢ËͽÓÊÕ8Î>>Ö¡½á¹¹
SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; //´®ÐÐͬ²½Ê±ÖӵĿÕÏÐ״̬Ϊ¸ßµçƽ
SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge; //´®ÐÐͬ²½Ê±Öӵĵڶþ¸öÌø±äÑØ£¨ÉÏÉý>>òϽµ£©Êý¾Ý±>>²ÉÑù
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; //NSSÐźÅÓÉÓ²¼þ£¨NSS¹Ü½Å£©>>¹ÊÇÈí¼þ£¨Ê¹ÓÃSSIÎ>>£©¹ÜÀí:ÄÚ²¿NSSÐźÅÓÐSSIÎ>>¿ØÖÆ
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256; //¶¨Ò岨ÌØÂÊÔ¤·ÖƵµÄÖµ:²¨ÌØÂÊÔ¤·ÖƵֵΪ256
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; //Ö¸¶¨Êý¾Ý´<<Êä´ÓMSBÎ>>>>¹ÊÇLSBÎ>>¿ªÊ¼:Êý¾Ý´<<Êä´ÓMSBÎ>>¿ªÊ¼
SPI_InitStructure.SPI_CRCPolynomial = 7; //CRCÖµ¼ÆËãµÄ¶àÏîʽ
SPI_Init(SPI1, &SPI_InitStructure); //¸ù¾ÝSPI_InitStructÖÐÖ¸¶¨µÄ²ÎÊý³õʼ>>¯ÍâÉèSPIx¼Ä´æÆ÷
SPI_Cmd(SPI1, ENABLE); //ʹÄÜSPIÍâÉè
SPI1_ReadWriteByte(0xff);//Æô¶¯´<<Êä
}
//SPI1ËÙ¶ÈÉèÖú¯Êý
//SPIËÙ¶È=fAPB2/·ÖƵϵÊý
//@ref SPI_BaudRate_Prescaler:SPI_BaudRatePrescaler_2~SPI_BaudRatePrescaler_256
//fAPB2ʱÖÓÒ>>°ãΪ84Mhz£º
void SPI1_SetSpeed(u8 SPI_BaudRatePrescaler)
{
assert_param(IS_SPI_BAUDRATE_PRESCALER(SPI_BaudRatePrescaler));//ÅжÏÓÐЧÐÔ
SPI1->CR1&=0XFFC7;//Î>>3-5ÇåÁ㣬ÓÃÀ´ÉèÖò¨ÌØÂÊ
SPI1->CR1|=SPI_BaudRatePrescaler; //ÉèÖÃSPI1ËÙ¶È
SPI_Cmd(SPI1,ENABLE); //ʹÄÜSPI1
}
//SPI1 ¶ÁдÒ>>¸ö×Ö½Ú
//TxData:ҪдÈëµÄ×Ö½Ú
//·µ>>ØÖµ:¶ÁÈ¡µ½µÄ×Ö½Ú
u8 SPI1_ReadWriteByte(u8 TxData)
{
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET){}//µÈ´ý·¢ËÍÇø¿Õ
SPI_I2S_SendData(SPI1, TxData); //ͨ¹ýÍâÉèSPIx·¢ËÍÒ>>¸öbyte Êý¾Ý
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET){} //µÈ´ý½ÓÊÕÍêÒ>>¸öbyte
return SPI_I2S_ReceiveData(SPI1); //·µ>>Øͨ¹ýSPIx×î½ü½ÓÊÕµÄÊý¾Ý
}
spi.h
#ifndef __SPI_H
#define __SPI_H
#include "sys.h"
void SPI1_Init(void); //³õʼ>>¯SPI1¿Ú
void SPI1_SetSpeed(u8 SpeedSet); //ÉèÖÃSPI1ËÙ¶È
u8 SPI1_ReadWriteByte(u8 TxData);//SPI1×ÜÏ߶ÁдÒ>>¸ö×Ö½Ú
#endif
3.i2c
(1)原理
I2C 是一种串行通信协议,用于连接微控制器或其他集成电路之间的通信。I2C协议使用两个信号线进行通信:串行数据线(SDA)和串行时钟线(SCL)。
I2C的工作原理如下:
- 主设备发送数据:主设备先发送起始信号,即将SDA从高电平拉低,然后再将SCL拉高。接着,主设备通过SDA线发送地址和数据位,每一位都在SCL的上升沿或下降沿进行采样。
- 从设备接收数据:从设备在SCL的上升沿或下降沿采样SDA线上的数据位。
- 主设备接收数据:主设备将SDA线拉低并将SCL线拉高,从设备将数据位写到SDA线上。接着,主设备在SCL的上升沿或下降沿采样数据位。
- 数据传输完成后,主设备发送停止信号,即将SDA从低电平拉高,然后再将SCL拉高。
I2C协议支持多主设备,即多个主设备可以在总线上进行通信。每个设备都有唯一的地址,主设备通过地址选择要与之通信的设备。I2C协议的传输速度相对较慢,但适用于短距离通信。
(2)日常的使用
首先i2c分为软件I2C和硬件I2C在一般的日常使用是使用软件i2c,因为I2C不能连接太多的设备,不存在像spi那么多的io口,只有数据线和时钟线,软件代码部分就相对复杂一点。最开始还是需要io初始化映射,然后设置I2C的开始和停止信号,设置应答信号,最后进行数据的发送接收。
(3)代码
MPUIIC.C
#include "mpuiic.h"
#include "delay.h"
//MPU IIC ÑÓʱº¯Êý
void MPU_IIC_Delay(void)
{
delay_us(2);
}
//³õʼ>>¯IIC
void MPU_IIC_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);//ÏÈʹÄÜÍâÉèIO PORTBʱÖÓ
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1|GPIO_Pin_0; // ¶Ë¿ÚÅäÖÃ
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; //ÍÆÍìÊä³ö
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO¿ÚËÙ¶ÈΪ50MHz
GPIO_Init(GPIOA, &GPIO_InitStructure); //¸ù¾ÝÉ趨²ÎÊý³õʼ>>¯GPIO
GPIO_SetBits(GPIOA,GPIO_Pin_1|GPIO_Pin_0);
}
//²úÉúIICÆðʼÐźÅ
void MPU_IIC_Start(void)
{
MPU_SDA_OUT(); //sdaÏßÊä³ö
MPU_IIC_SDA=1;
MPU_IIC_SCL=1;
MPU_IIC_Delay();
MPU_IIC_SDA=0;//START:when CLK is high,DATA change form high to low
MPU_IIC_Delay();
MPU_IIC_SCL=0;//ǯסI2C×ÜÏߣ¬×¼±¸·¢ËÍ>>ò½ÓÊÕÊý¾Ý
}
//²úÉúIICÍ£Ö¹ÐźÅ
void MPU_IIC_Stop(void)
{
MPU_SDA_OUT();//sdaÏßÊä³ö
MPU_IIC_SCL=0;
MPU_IIC_SDA=0;//STOP:when CLK is high DATA change form low to high
MPU_IIC_Delay();
MPU_IIC_SCL=1;
MPU_IIC_SDA=1;//·¢ËÍI2C×ÜÏß½áÊøÐźÅ
MPU_IIC_Delay();
}
//µÈ´ýÓ¦´ðÐźŵ½À´
//·µ>>ØÖµ£º1£¬½ÓÊÕÓ¦´ðʧ°Ü
// 0£¬½ÓÊÕÓ¦´ð³É¹¦
u8 MPU_IIC_Wait_Ack(void)
{
u8 ucErrTime=0;
MPU_SDA_IN(); //SDAÉèÖÃΪÊäÈë
MPU_IIC_SDA=1;MPU_IIC_Delay();
MPU_IIC_SCL=1;MPU_IIC_Delay();
while(MPU_READ_SDA)
{
ucErrTime++;
if(ucErrTime>250)
{
MPU_IIC_Stop();
return 1;
}
}
MPU_IIC_SCL=0;//ʱÖÓÊä³ö0
return 0;
}
//²úÉúACKÓ¦´ð
void MPU_IIC_Ack(void)
{
MPU_IIC_SCL=0;
MPU_SDA_OUT();
MPU_IIC_SDA=0;
MPU_IIC_Delay();
MPU_IIC_SCL=1;
MPU_IIC_Delay();
MPU_IIC_SCL=0;
}
//²>>²úÉúACKÓ¦´ð
void MPU_IIC_NAck(void)
{
MPU_IIC_SCL=0;
MPU_SDA_OUT();
MPU_IIC_SDA=1;
MPU_IIC_Delay();
MPU_IIC_SCL=1;
MPU_IIC_Delay();
MPU_IIC_SCL=0;
}
//IIC·¢ËÍÒ>>¸ö×Ö½Ú
//·µ>>Ø´Ó>>úÓÐÎÞÓ¦´ð
//1£¬ÓÐÓ¦´ð
//0£¬ÎÞÓ¦´ð
void MPU_IIC_Send_Byte(u8 txd)
{
u8 t;
MPU_SDA_OUT();
MPU_IIC_SCL=0;//ÀµÍʱÖÓ¿ªÊ¼Êý¾Ý´<<Êä
for(t=0;t<8;t++)
{
MPU_IIC_SDA=(txd&0x80)>>7;
txd<<=1;
MPU_IIC_SCL=1;
MPU_IIC_Delay();
MPU_IIC_SCL=0;
MPU_IIC_Delay();
}
}
//¶Á1¸ö×Ö½Ú£¬ack=1ʱ£¬·¢ËÍACK£¬ack=0£¬·¢ËÍnACK
u8 MPU_IIC_Read_Byte(unsigned char ack)
{
unsigned char i,receive=0;
MPU_SDA_IN();//SDAÉèÖÃΪÊäÈë
for(i=0;i<8;i++ )
{
MPU_IIC_SCL=0;
MPU_IIC_Delay();
MPU_IIC_SCL=1;
receive<<=1;
if(MPU_READ_SDA)receive++;
MPU_IIC_Delay();
}
if (!ack)
MPU_IIC_NAck();//·¢ËÍnACK
else
MPU_IIC_Ack(); //·¢ËÍACK
return receive;
}
MPUIIC.H
#ifndef __MPUIIC_H
#define __MPUIIC_H
#include "sys.h"
/
//IO·½ÏòÉèÖÃ
#define MPU_SDA_IN() {GPIOA->MODER&=~(3<<(1*2));GPIOA->MODER|=0<<1*2;} //PA1ÊäÈëģʽ
#define MPU_SDA_OUT() {GPIOA->MODER&=~(3<<(1*2));GPIOA->MODER|=1<<1*2;} //PA1Êä³öģʽ
//IO²Ù×÷º¯Êý
#define MPU_IIC_SCL PAout(0) //SCL
#define MPU_IIC_SDA PAout(1) //SDA
#define MPU_READ_SDA PAin(1) //SDA
//IICËùÓвÙ×÷º¯Êý
void MPU_IIC_Delay(void); //MPU IICÑÓʱº¯Êý
void MPU_IIC_Init(void); //³õʼ>>¯IICµÄIO¿Ú
void MPU_IIC_Start(void); //·¢ËÍIIC¿ªÊ¼ÐźÅ
void MPU_IIC_Stop(void); //·¢ËÍIICÍ£Ö¹ÐźÅ
void MPU_IIC_Send_Byte(u8 txd); //IIC·¢ËÍÒ>>¸ö×Ö½Ú
u8 MPU_IIC_Read_Byte(unsigned char ack);//IIC¶ÁÈ¡Ò>>¸ö×Ö½Ú
u8 MPU_IIC_Wait_Ack(void); //IICµÈ´ýACKÐźÅ
void MPU_IIC_Ack(void); //IIC·¢ËÍACKÐźÅ
void MPU_IIC_NAck(void); //IIC²>>·¢ËÍACKÐźÅ
void IMPU_IC_Write_One_Byte(u8 daddr,u8 addr,u8 data);
u8 MPU_IIC_Read_One_Byte(u8 daddr,u8 addr);
#endif