1、串行通信
2、常见的4种串行通信标准
3、对74LS164芯片的介绍
74LS164:串行转并行芯片,内部是1个8位的移位寄存器组成,由8个D触发器组成
缺点是:不带锁存寄存器,移位寄存器移位的过程会表现在164的输出引脚上,容易产生输出干扰。
4、用KEIL4进行软件仿真时,按正常步骤建立工程,然后在下图位置按照下图设置即可。
5、软件仿真:STM32与74LS164进行通信的程序如下:
/**************************************************************************************************
* 硬件平台:STM32F103VC
* 学习重点:GPIOx的位绑定
* 实现功能:软件仿真,实现STM32与“串行转并行芯片164”进行通信
* 164不带锁存器,给它串行传数据时,内部移位寄存器的移位过程会在其并行输出引脚上表现出来
* Clear引脚低电平有效,接STM32的PB.0引脚 Clock上升沿有效,接STM32的PA.1引脚
* A&B 相与后作为164的串行输入引脚
**************************************************************************************************/
/*=============================================================================
* 位绑定公式:
* 1、SRAM区域 :0X2200 0000 ----0X200F FFFF
* Aliasaddr = 0X22000000 + ( A -0X20000000 )*32 + n*4
* 2、片上外设区域 :0X4200 0000 ----0X400F FFFF
* Aliasaddr = 0X42000000 + ( A -0X40000000 )*32 + n*4
* 参数解释:
* Aliasaddr : 设置“端口GPIOx的第n位”的寄存器_相应位的实际地址
* A : 端口GPIOx的基地址(GPIOx_BASE) + 相应寄存器的偏移地址
* n : 配置的是相应寄存器的第n位
* 寄存器的偏移地址 :CRL CRH IDR ODR BSRR BRR LCKR
* 00H 04H 08H 0CH 10H 14H 18H
=============================================================================*/
/* Includes ------------------------------------------------------------------*/
#include "stm32f10x_lib.h" //包含了所有的头文件 它是唯一一个用户需要包括在自己应用中的文件,起到应用和库之间界面的作用。
#include "stm32f10x_map.h"
/******************************快速位绑定**********************************************************/
/*----------------1、宏定义要操作的寄存器地址---------------------------------------------*/
#define GPIOA_ODR (GPIOA_BASE + 0X0C)
#define GPIOA_IDR (GPIOA_BASE + 0X08)
#define GPIOB_ODR (GPIOB_BASE + 0X0C)
#define GPIOB_IDR (GPIOB_BASE + 0X08)
#define GPIOC_ODR (GPIOC_BASE + 0X0C)
#define GPIOC_IDR (GPIOC_BASE + 0X08)
#define GPIOD_ODR (GPIOD_BASE + 0X0C)
#define GPIOD_IDR (GPIOD_BASE + 0X08)
#define GPIOE_ODR (GPIOE_BASE + 0X0C)
#define GPIOE_IDR (GPIOE_BASE + 0X08)
/*----------------2、获取端口GPIOx(A-E)的对应寄存器的某一操作位的位地址-------------------*/
// #define BitBand(Addr , BitNum) *( (volatile unsigned long *)(Addr & 0xf0000000) + 0x2000000 + ((Addr&0xfffff)*32) + (BitNum*4) )
// 因为 左移、右移 语句的执行速度比乘除法语句的运动速度快,所以将上述语句改成如下方式
#define BitBand(Addr , BitNum) *( (volatile unsigned long *)( (Addr & 0xf0000000) + 0x2000000 + ((Addr&0xfffff)<<5) + (BitNum<<2) ) )
/*----------------3、宏定义函数,对固定的位绑定 进行功能封装------------------------------*/
#define PAout(n) BitBand(GPIOA_ODR , n)
#define PAin(n) BitBand(GPIOA_IDR , n)
#define PBout(n) BitBand(GPIOB_ODR , n)
#define PBin(n) BitBand(GPIOB_IDR , n)
#define PCout(n) BitBand(GPIOC_ODR , n)
#define PCin(n) BitBand(GPIOC_IDR , n)
#define PDout(n) BitBand(GPIOD_ODR , n)
#define PDin(n) BitBand(GPIOD_IDR , n)
#define PEout(n) BitBand(GPIOE_ODR , n)
#define PEin(n) BitBand(GPIOE_IDR , n)
/*----------------函数声明部分---------------*/
void delay1ms(int t) ;
/* Private functions -----------------------------------------------------------------------------*/
/**************************************************************************************************
* Function Name : main
* Description : 从GPIOA.8-.16输入一个电平信号,GPIOA.0-.7口分别将对应引脚输入的电平信号输出
* Input : None
* Output : None
* Return : None
****************************************************************************************************/
int main(void)
{
u8 i , data ;
/*--------控制STM32引脚GPIOA.0 GPIOA.1 GPIOB.0推挽输出高电平--------*/
//1、设置GPIOA.0--A&B GPIOA.1--CLOCK GPIOB.0--CLEAR
//GPIOA.0 GPIOA.1 GPIOB.0推挽输出,速度50MHZ
GPIOA->CRL = 0x33 ; // CNF0 = 00 MODE0 = 11
GPIOB->CRL = 0x03 ; // CNF0 = 00 MODE0 = 11
//GPIOA->CRH = 0x44444444 ; // CNF0 = 01 MODE0 = 00
//2、与164进行通信,QA--QH : 01100101 ,PA0串行输出,PA1上升沿有效,PB0=0清零 =1传数据
data = 0x65 ;
//初次使用164,先对其进行清零 CLOCK = 0 然后 CLOCK = 1 , PA1 ——> CLOCK 先置为低电平,为缠上上升沿做准备
PBout(0) = 0 ;
PAout(1) = 0 ;
PBout(0) = 1 ;
//向164串行传送8位数据
for(i = 0 ; i < 8 ; i++)
{
PAout(1) = 0 ;
delay1ms(1) ; //CLOCK的低电平维持1ms
if((data&0x01) == 0x01)
{
PAout(0) = 1 ;
}
else
{
PAout(0) = 0 ;
}
PAout(1) = 1 ;
delay1ms(1) ;//CLOCK的高电平维持1ms
data = data >> 1 ;
}
// while(1)
// {
// ;
// }
//
// return 1 ;
}
void delay1ms(int t)
{
//机器周期T = 1/(72000000/12)s = 1/6000000 s = 1/6 us
int temp = 6000/4 ;
while(t--)
{
while(temp--)
{ ; }
}
}
6、软件仿真结果如下: