由于MSP430F169单片机含有两个USART串口通信模块,都可以作为SPI同步通信,所以可以实现单片机自身的同步通信。
1 #include <msp430f169.h> 2 //延时函数 3 #define CPU_F ((double)8000000) //外部高频晶振8MHZ 4 #define delay_us(x) __delay_cycles((long)(CPU_F*(double)x/1000000.0)) 5 #define delay_ms(x) __delay_cycles((long)(CPU_F*(double)x/1000.0)) 6 7 //自定义数据结构,方便使用 8 #define uchar unsigned char 9 #define uint unsigned int 10 #define ulong unsigned long 11 //串口波特率计算,当BRCLK=CPU_F时用下面的公式可以计算,否则要根据设置加入分频系数 12 #define baud 9600 //设置波特率的大小 13 #define baud_setting (uint)((ulong)CPU_F/((ulong)baud)) //波特率计算公式 14 #define baud_h (uchar)(baud_setting>>8) //提取高位 15 #define baud_l (uchar)(baud_setting) //低位 16 //LMB162液晶控制管脚配置 17 #define DataDIR P4DIR //数据口方向 18 #define DataPort P4OUT //P4口为数据口 19 20 #define RS_0 P5OUT &= ~BIT5 //RS置低 21 #define RS_1 P5OUT |= BIT5 //RS置高 22 23 #define RW_0 P5OUT &= ~BIT6 //RW置低 24 #define RW_1 P5OUT |= BIT6 //RW置高 25 26 #define EN_0 P5OUT &= ~BIT7 //E置低 27 #define EN_1 P5OUT |= BIT7 //E置高 28 /** 29 * 系统时钟初始化,外部8M晶振 30 */ 31 void CLOCK_Init() 32 { 33 uchar i; 34 BCSCTL1&=~XT2OFF; //打开XT2振荡器 35 BCSCTL2|=SELM1+SELS; //MCLK为8MHZ,SMCLK为8MHZ 36 do{ 37 IFG1&=~OFIFG; //清除振荡器错误标志 38 for(i=0;i<100;i++) 39 _NOP(); 40 } 41 while((IFG1&OFIFG)!=0); //如果标志位1,则继续循环等待 42 IFG1&=~OFIFG; 43 } 44 /** 45 *显示屏命令写入函数 46 */ 47 void LCD_write_com(unsigned char com) 48 { 49 RS_0; 50 RW_0; 51 DataPort = com; //命令写入端口 52 EN_1; 53 delay_ms(5); 54 EN_0; 55 delay_ms(5); 56 } 57 /** 58 * 显示屏数据写入函数 59 */ 60 void LCD_write_data(unsigned char data) 61 { 62 RS_1; 63 RW_0; 64 DataPort = data; //数据写入端口 65 EN_1; 66 delay_ms(5); 67 EN_0; 68 delay_ms(5); 69 } 70 /** 71 * 显示屏字符串写入函数 72 */ 73 void LCD_write_str(unsigned char H,unsigned char L,unsigned char *s) 74 { 75 76 if (H == 0) 77 { 78 LCD_write_com(0x80 + L); //第一行显示 79 } 80 else 81 { 82 LCD_write_com(0xC0 + L); //第二行显示 83 } 84 85 while (*s) 86 { 87 LCD_write_data( *s); 88 s ++; 89 } 90 } 91 /** 92 * 显示屏单字符写入函数 93 */ 94 void LCD_write_char(unsigned char H,unsigned char L,unsigned char data) 95 { 96 97 if (H == 0) 98 { 99 LCD_write_com(0x80 + L); //第一行显示 100 } 101 else 102 { 103 LCD_write_com(0xC0 + L); //第二行显示 104 } 105 106 LCD_write_data( data); 107 } 108 /** 109 * 显示屏初始化函数 110 */ 111 void LCD_init(void) 112 { 113 EN_0; 114 LCD_write_com(0x38); //显示模式设置 115 delay_ms(5); 116 LCD_write_com(0x08); //显示关闭 117 delay_ms(5); 118 LCD_write_com(0x01); //显示清屏 119 delay_ms(5); 120 LCD_write_com(0x06); //显示光标移动设置 121 delay_ms(5); 122 LCD_write_com(0x0C); //显示开及光标设置 123 delay_ms(5); 124 } 125 /* 126 * 主机SPI初始化 127 */ 128 void Init_M_SPI() 129 { 130 U0CTL |=SWRST; 131 P3SEL |=BIT1+BIT2+BIT3; 132 U0CTL |= CHAR+SYNC+MM; //U0SART_SPI 8位字符 SPI 主机模式 133 U0TCTL |= CKPH+SSEL1+STC; //主机:SMCLK作为SPI时钟,3线模式 134 U0BR0 = baud_l; 135 U0BR1 = baud_h; 136 U0MCTL = 0x00; 137 ME1 = USPIE0; //USART0 SPI使能 138 U0CTL &=~SWRST; 139 IE1 &=~UTXIE0; 140 IE1 &=~URXIE0; 141 P3DIR |=BIT1; 142 143 } 144 /* 145 * 从机SPI初始化 146 */ 147 void Init_S_SPI() 148 { 149 U1CTL |=SWRST; 150 P5SEL |=BIT1+BIT2+BIT3; 151 U1CTL = CHAR+SYNC; //U1SART_SPI 8位字符 SPI 从机模式 152 U1TCTL = CKPL+STC; //从机:外部时钟,3线模式 153 ME2 = USPIE1; //USART1 SPI使能 154 U1CTL &=~SWRST; 155 IE2 = URXIE1; 156 P5DIR |=BIT2; 157 } 158 /* 159 *主机单字符发送函数 160 */ 161 void Send_Byte(uchar data) 162 { 163 U0TXBUF = data; 164 while((IFG1&UTXIFG0)==0); 165 IFG1 &=~UTXIFG0; 166 } 167 #pragma vector=USART1RX_VECTOR 168 __interrupt void USART1RX(void) 169 { 170 uchar data; 171 data = U1RXBUF; 172 LCD_write_char(1,15,data); 173 delay_ms(5); 174 } 175 /* 176 * 键盘扫描 177 */ 178 uchar key_scan(){ 179 uchar a=1,s,count=1; 180 uchar value=0; 181 for(a=1;a<0x10;a<<=1){ 182 P2DIR = 0xFF; 183 P2OUT = 0x00; 184 P2DIR=0x0f; 185 P2OUT=a; 186 if(P2IN!=a){ 187 if(0x10&P2IN) 188 s=0; 189 if(0x20&P2IN) 190 s=1; 191 if(0x40&P2IN) 192 s=2; 193 if(0x80&P2IN) 194 s=3; 195 value=s*4+count+'0'; 196 } 197 count++; 198 } 199 return value; 200 } 201 /** 202 * 主函数 203 */ 204 void main(void) 205 { 206 WDTCTL = WDTPW | WDTHOLD; // 关闭看门狗 207 P4SEL = 0x00; 208 P4DIR = 0xFF; //数据口输出模式 209 P5SEL =(P5SEL&0x8F); 210 P5DIR|= BIT5 + BIT6 + BIT7; //控制口设置为输出模式 211 CLOCK_Init(); 212 Init_M_SPI(); 213 Init_S_SPI(); 214 LCD_init(); 215 uchar temp=0; 216 _EINT(); 217 while(1){ 218 LCD_write_str(0,0,"*COM-MSP430-SPI*"); 219 LCD_write_str(1,0,"KEY="); 220 LCD_write_str(1,11,"COM="); 221 delay_ms(5); 222 if(key_scan()==0) 223 continue; 224 else 225 { 226 temp = key_scan(); 227 delay_ms(5); 228 LCD_write_char(1,4,temp); 229 delay_ms(5); 230 Send_Byte(temp); 231 } 232 } 233 }