本帖最后由 wenyangzeng 于 2017-4-5 14:58 编辑
toofree 发表于 2017-4-5 14:44
你这个应该用上升沿或下降沿读取吧,你用电平肯定不行呀,而且中间没有延时,循环太快太快了。你循环结束 ...
按照你例程每接收1个bit延时1毫秒,接收1个字节就需要8毫秒,怎么受得了?如果不可靠,顶多在时钟沿到来之后加1-2个NOP足够矣。
纳秒级的呀:
为何不用上升沿/下降沿中断触发方式读取???
曾做过测试,使用电平方式特别容易受干扰,而是用上升沿/下降沿触发方式则可靠得多
wenyangzeng 发表于 2017-4-5 14:53
按照你例程每接收1个bit延时1毫秒,接收1个字节就需要8毫秒,怎么受得了?如果不可靠,顶多在时钟沿到来之 ...
不好意,看错了。以为是楼主的帖子,被程序给误导了。
楼主,把程序注释弄成能显示的字符吧,这乱码猜不到是什么意思。或者发一个原理图。
本帖最后由 toofree 于 2017-4-5 16:14 编辑
unsigned char i;
ADDR_SW_Data = 0;
GPIO_ResetBits(GPIOC, 2); // clock_en,165时钟消禁止位,1禁止,0使能。使能
GPIO_ResetBits(GPIOC, 1); // PL,165移位/加载位,1移位,0加载。加载
delay_ms(1);
GPIO_SetBits(GPIOC, 1); //PL,加载并行数据
delay_ms(1);
for(i=0;i<16;i++)//16次循环读取
{
GPIO_ResetBits(GPIOC, 0);//clock
delay_us(10);
GPIO_SetBits(GPIOC, 0); //clock,上升沿,D触发器打数
delay_us(5); //这里为什么要加个延时呢?D触发器打数到稳定需要时间;STM32的IO管脚接收到数据,到数据稳定也需要时间。不见得非得是5us,但必须有
ADDR_SW_Data = GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_3) | (ADDR_SW_Data<<1); //之前数据左移1位,加上读取到的最低位
delay_us(5);//补上5us,凑出20us,50%占空比
}
GPIO_SetBits(GPIOC, 2); //clock_en,禁止时钟
GPIO_ResetBits(GPIOC,1);//PL,加载并行数据
没问题,我的程序可以了,只是我设置上的问题
#include "74HC165D.h"
#include "delay.h"
#include "485test.h"
unsigned int ADDR_SW_Data,HC=0;
void ADDR_SW_Init(void)//74HC165D各引脚初始化
{
GPIO_InitTypeDef ADDR_SW_GPIO_InitStructure;
/* GPIOD Periph clock enable */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE); //
/* Configure zoom and focus pins in output pushpull mode */
ADDR_SW_GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2;//0:clock;1:PL;2:clock_en
GPIO_SetBits(GPIOC, GPIO_Pin_0);//clock
GPIO_SetBits(GPIOC, GPIO_Pin_1);//PL
GPIO_SetBits(GPIOC, GPIO_Pin_2);//clock_en
ADDR_SW_GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
ADDR_SW_GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
GPIO_Init(GPIOC, &ADDR_SW_GPIO_InitStructure);
/* Configure SPI1 pins: MISO and MOSI */
ADDR_SW_GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;//DATA_OUT
ADDR_SW_GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空输入
GPIO_Init(GPIOC, &ADDR_SW_GPIO_InitStructure);
}
void read_ADDR_SW(void)//读取74HC165D函数值
{
unsigned char i;
ADDR_SW_Data = 0;
GPIO_ResetBits(GPIOC, GPIO_Pin_2);//clock_en //打开165选通端
GPIO_ResetBits(GPIOC, GPIO_Pin_1); //运行数据计入165
delay_ms(1);
GPIO_SetBits(GPIOC, GPIO_Pin_1); //允许数据移位
for(i=0;i<16;i++) //读16次数据
{
GPIO_ResetBits(GPIOC, GPIO_Pin_0);
delay_ms(1);
ADDR_SW_Data = GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_3) | (ADDR_SW_Data<<1);
GPIO_SetBits(GPIOC, GPIO_Pin_0);
delay_ms(1);
}
GPIO_SetBits(GPIOC, GPIO_Pin_2); //关闭165选通端
GPIO_ResetBits(GPIOC, GPIO_Pin_1); //运行数据计入165
ADDR_SW_Data = ~ADDR_SW_Data; //拨码开关取反
//PT_currentaddr = ADDR_SW_Data & 0x00ff; //拨码开关低8位为地址
switch((ADDR_SW_Data >> 8) & 0x0003) //拨码开关高8位为波特率设置,低2位为波特率设置位
{
case 0x0000 :
{
//current_BautRate = 2400;
USART_SendData(USART1, 1);
while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);//检测发送状态寄存器
break ;
}
case 0x0001 :
{
//current_BautRate = 4800;
USART_SendData(USART1, 2);
while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);//检测发送状态寄存器
break ;
}
case 0x0002 :
{
//current_BautRate = 9600;
USART_SendData(USART1,3);
while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);//检测发送状态寄存器
break ;
}
case 0x0003 :
{
//current_BautRate = 19200;
USART_SendData(USART1, 4);
while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);//检测发送状态寄存器
break ;
}
default :
//current_BautRate = 2400;
{USART_SendData(USART1, 1);
while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);//检测发送状态寄存器
}
break ;
}
}
检测口试试使用GPIO_Mode_IPU上拉输入,不要用浮空
74HC165,我用来做按键,接了三个74HC165,还有LED共用,
项目有点相同。74HC165用处多多。