要做个项目需要7个串口,MCU上串口不够需要自己模拟,就到本论坛上找,不过没找到,最终找了下资料用原子哥的串口实验例程改的,成功了拿来分享一下,要是有什么问题也希望大家指点一下,
平时老是从这里获取,也希望能为论坛做点贡献。
为了方便跟电脑串口连接,io口仍选用PA9与PA10,不过这里只将它们当作变通的IO口使用。PA9对应TXD,PA10对应RXD的功能。串口配置是波特率9600,8位数据位,1位停止位,无校验位。
不过我也有个疑问,因为这个是按照原子哥的串口例程改的,所以结束标志就是收到0x0d,0x0a,这样就必须发字符串的时候发送新行,发16进制数最后要有0x0d,0x0a。我看到我往串口调试助手发送数据,根本就没发固定的结束标志啊,它都能立即接收并显示出来,它是依次接收一个字节就显示一个字节吗?我试了一下,只能正常接收第一个字节后面的都丢了。
发送数据:
void SendOneByte(u8 Byte)
{
u8 i=8,tmp;
TXD_low(); //发送起始位
delay_us(104);
//发送8位数据
for(i=0;i<8;i++)
{
tmp = (Byte >> i) & 0x01; //低位在前
if(tmp == 0)
{
TXD_low();
delay_us(104); //0
}
else
{
TXD_high();
delay_us(104); //1
}
}
// while(i--)
// {
// MNUSART_TXD = (Byte&0x01); //先传低位
// delay_us(104);
// Byte = Byte>>1;
// //无校验位
// MNUSART_TXD=1;//发送结束位
// delay_us(104);
// }
TXD_high();
delay_us(104);
}
void SendBytes(u8 *str,u8 len) //发送数组最好用这个,也可发送字符串
{
u16 i;
for(i=0;i<len;i++)
{
SendOneByte(str);
}
}
void SendStr(u8 *str) //发送字符串,发送数组如果带0x00就中断发送了
{
while(*str)
SendOneByte(*str++);
}
接收用的外部中断:
void EXTIX_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
EXTI_InitTypeDef EXTI_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO,ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9 端口配置
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO口速度为50MHz
GPIO_Init(GPIOA, &GPIO_InitStructure); //根据设定参数初始化GPIOB.5
GPIO_SetBits(GPIOA,GPIO_Pin_9);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //浮空输入
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_SetBits(GPIOA,GPIO_Pin_10);
//GPIOA.10 中断线以及中断初始化配置 下降沿触发
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource10);
EXTI_InitStructure.EXTI_Line=EXTI_Line10;
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寄存器
NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority =0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
void EXTI15_10_IRQHandler(void)
{
u8 i=9;
if(EXTI_GetITStatus(EXTI_Line10) != RESET)
{
/* Disable the Selected IRQ Channels -------------------------------------*/
NVIC->ICER[EXTI15_10_IRQn >> 0x05] =
(uint32_t)0x01 << (EXTI15_10_IRQn & (uint8_t)0x1F);
EXTI_ClearITPendingBit(EXTI_Line10);
delay_us(30);
while(i--)
{
tmp >>=1;
if(GPIOA->IDR&0x0400) tmp |=0x80;
delay_us(104);
}
if((USART_RX_STA&0x8000)==0)
{
if(USART_RX_STA&0x4000)
{
if(tmp!=0x0a) USART_RX_STA=0;
else USART_RX_STA |=0x8000;
}
else
{
if(tmp==0x0d) USART_RX_STA|=0x4000;
else
{
USART_RX_BUF[USART_RX_STA&0X3FFF]=tmp ;
USART_RX_STA++;
if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;//接收数据错误,重新开始接收
}
}
}
EXTI_ClearITPendingBit(EXTI_Line10);
NVIC->ISER[EXTI15_10_IRQn >> 0x05] =
(uint32_t)0x01 << (EXTI15_10_IRQn & (uint8_t)0x1F);
}
}
主函数:
int main(void)
{
u8 len;
u8 hello[]={0x5a,0xa5,0x00,0x00,0x01};
delay_init();
EXTIX_Init();
//测试 发送一个字节
SendOneByte(0x00);
SendOneByte(0x01);
SendOneByte(0x02);
//测试发送数组
SendBytes(hello,5);
//测试发送字符串
// SendBytes("hello word",11);
// SendStr("德玛西亚");
while(1)
{
if(USART_RX_STA&0x8000)
{
printf("
您发送的消息为:
");
len=USART_RX_STA&0x3fff;//得到此次接收到的数据长度
SendBytes(USART_RX_BUF,len);
//也可以用下面的发送
// SendStr(USART_RX_BUF);
// for(len=0;len<200;len++)
// USART_RX_BUF[len]=0;
printf("
");//插入换行
USART_RX_STA=0;
}
}
}
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
---------------------------------
这个我只在430中用过,因为工作用的430,首先如果使用这种方法,得根据时钟和波特率设置好1个bit的时间,也就是捕获和比较中断的时间,发送的话,定义一个16bit变量txd,然后将要发送的8bit数据插入起始位和停止位比如一个起始位一个停止位,就变成了10bit数据送给16位变量txd,开启比较中断,然后只需要在比较中断中按顺序判断txd的每一位,高就输出高,低就输出低,直到10个bit发送完毕即可关闭比较输出,一个字节就发送完成了。TX可以用通用IO也可以用比较输出引脚,具体情况而定。
一周热门 更多>